欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C语言学习教程:超级玛丽游戏开发源码分享

程序员文章站 2022-03-25 22:56:16
c语言写的超级玛丽游戏源代码,学习之余还可以重温一下儿时的经典。益智游戏,较为广泛的流通。马里奥是站在游戏界顶峰的超人气多面角色 ......

c语言写的超级玛丽游戏源代码,学习之余还可以重温一下儿时的经典。

益智游戏,较为广泛的流通。马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带工作服、还留着胡子。与他的双胞胎兄弟路易一起,长年担任任天堂的超级大牌角色。这款很经典的红白机游戏,唤起了大家儿时的快乐时光。快点来尝试下吧!此次推出的是完美版,完美音效、键盘操作更加灵敏、玛丽生命无限

C语言学习教程:超级玛丽游戏开发源码分享

这里推荐一下我建的c/c++语言学习交流秋秋裙,前三位是:110,中间三位是:355,最后三位是:025,为了让学习变得轻松,高效!给大家分享一套教学资源,帮助大家在成为c/c++语言开发高手的道路上披荆斩棘,群内每晚八点免费直播授课,讲解c/c++语言案例,同时还有c/c++语言大牛在线解答问题!虽然说c/c++语言开发发展前景好,但易学难精。由于入门容易这也导致了市场上人员泛滥、人才稀缺的局面产生。但是在互联网越来越强烈的竞争下,这样的人也最终会被市场淘汰。

 

超级玛丽游戏开发源码

  1 <!doctype html public "-//w3c//dtd html 4.0 transitional//en">
  2 <html>
  3  <head>
  4   <title> new document </title>
  5   <meta name="generator" content="editplus">
  6   <meta name="author" content="">
  7   <meta name="keywords" content="">
  8   <meta name="description" content="">
  9   <style type="text/css">
 10   *body{margin:0 auto;}
 11   #status{
 12     position: absolute;
 13     left: 50%;
 14     top: 170px;
 15     margin-left: 60px;
 16   }
 17 .background {
 18   background: rgb(52, 166, 251);
 19   table-layout: fixed;
 20   border-spacing: 0;
 21 }
 22 .background td { padding: 0; }
 23 .lava { background: rgb(255, 100, 100); }
 24 .wall { background: white; }
 25 .actor { position: absolute; }
 26 .coin { background: rgb(241, 229, 89); }
 27 .player { background: rgb(64, 64, 64); }
 28 .lost .player { background: rgb(160, 64, 64); }
 29 .won .player {
 30   box-shadow: -4px -7px 8px white, 4px -7px 8px white;
 31 }
 32 .game {
 33   overflow: hidden;
 34   max-width: 600px;
 35   max-height: 450px;
 36   position: relative;
 37 }
 38   </style>
 39 </head>
 40  
 41 <body>
 42 <!--<img style="position: absolute;right: 0;top: 0;" src=" http://a4.qpic.cn/psb?/v13id91s0o4nyt/y9r.1dx5wxfyfzzdqbmg2hsjlt7lizjpocpyg.6gxhk!/b/dembaaaaaaaa&ek=1&kp=1&pt=0&bo=lagyaqaaaaarf74!&vuin=206105759&tm=1522486800&sce=60-2-2&rf=viewer_4">-->
 43  <div id='status'>how many lives you have left: <span id="lives"></span></div>
 44 <script type="text/javascript">
 45   
 46   /*
 47 based on dark blue by thomas palef.
 48 plans are submitted as an array of strings that forms a grid.
 49 @ = player start position
 50 o = coins
 51 x = solid surfaces
 52 ! = non-moving lava
 53 = = vertical moving lava
 54 v = dripping lava
 55 | = horizontal moving lava
 56 */
 57 var simplelevelplan = [
 58   "                      ",
 59   "                      ",
 60   "  x              = x  ",
 61   "  x         o o    x  ",
 62   "  x @      xxxxx   x  ",
 63   "  xxxxx            x  ",
 64   "      x!!!!!!!!!!!!x  ",
 65   "      xxxxxxxxxxxxxx  ",
 66   "                      "
 67 ];
 68  
 69 var game_levels = [
 70   ["                                                                                ",
 71    "                                                                                ",
 72    "                                                                                ",
 73    "                                                                                ",
 74    "                                                                                ",
 75    "                                                                                ",
 76    "                                                                  xxx           ",
 77    "                                                   xx      xx    xx!xx          ",
 78    "                                    o o      xx                  x!!!x          ",
 79    "                                                                 xx!xx          ",
 80    "                                   xxxxx                          xxx           ",
 81    "                                                                            xx  ",
 82    "  xx                                      o o                                x  ",
 83    "  x                     o                                                    x  ",
 84    "  x                                      xxxxx                             o x  ",
 85    "  x          xxxx       o                                                    x  ",
 86    "  x  @       x  x                                                xxxxx       x  ",
 87    "  xxxxxxxxxxxx  xxxxxxxxxxxxxxx   xxxxxxxxxxxxxxxxxxxx     xxxxxxx   xxxxxxxxx  ",
 88    "                              x   x                  x     x                    ",
 89    "                              x!!!x                  xooooox                    ",
 90    "                              xooox                  xooooox                    ",
 91    "                              xxxxx                  xxxxxxx                    ",
 92    "                                                                                ",
 93    "                                                                                "],
 94   ["                                      x!!x                        xxxxxxx                                    x!x  ",
 95    "                                      x!!x                     xxxx     xxxx                                 x!x  ",
 96    "                                      x!!xxxxxxxxxx           xx           xx                                x!x  ",
 97    "                                      xx!!!!!!!!!!xx         xx             xx                               x!x  ",
 98    "                                       xxxxxxxxxx!!x         x                                    o   o   o  x!x  ",
 99    "                                                xx!x         x     o   o                                    xx!x  ",
100    "                                                 x!x         x                                xxxxxxxxxxxxxxx!!x  ",
101    "                                                 xvx         x     x   x                        !!!!!!!!!!!!!!xx  ",
102    "                                                             xx  |   |   |  xx            xxxxxxxxxxxxxxxxxxxxx   ",
103    "                                                              xx!!!!!!!!!!!xx            v                        ",
104    "                                                               xxxx!!!!!xxxx                                      ",
105    "                                               x     x            xxxxxxx        xxx         xxx                  ",
106    "                                               x     x                           x x         x x                  ",
107    "                                               x     x                             x         x                    ",
108    "                                               x     x                             xx        x                    ",
109    "                                               xx    x                             x         x                    ",
110    "                                               x     x      o  o     x   x         x         x                    ",
111    "               xxxxxxx        xxx   xxx        x     x               x   x         x         x                    ",
112    "              xx     xx         x   x          x     x     xxxxxx    x   x   xxxxxxxxx       x                    ",
113    "             xx       xx        x o x          x    xx               x   x   x               x                    ",
114    "     @       x         x        x   x          x     x               x   x   x               x                    ",
115    "    xxx      x         x        x   x          x     x               x   xxxxx   xxxxxx      x                    ",
116    "    x x      x         x       xx o xx         x     x               x     o     x x         x                    ",
117    "!!!!x x!!!!!!x         x!!!!!!xx     xx!!!!!!!!xx    x!!!!!!!!!!     x     =     x x         x                    ",
118    "!!!!x x!!!!!!x         x!!!!!xx       xxxxxxxxxx     x!!!!!!!xx!     xxxxxxxxxxxxx xx  o o  xx                    ",
119    "!!!!x x!!!!!!x         x!!!!!x    o                 xx!!!!!!xx !                    xx     xx                     ",
120    "!!!!x x!!!!!!x         x!!!!!x                     xx!!!!!!xx  !                     xxxxxxx                      ",
121    "!!!!x x!!!!!!x         x!!!!!xx       xxxxxxxxxxxxxx!!!!!!xx   !                                                  ",
122    "!!!!x x!!!!!!x         x!!!!!!xxxxxxxxx!!!!!!!!!!!!!!!!!!xx    !                                                  ",
123    "!!!!x x!!!!!!x         x!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!xx     !                                                  "],
124   ["                                                                                                              ",
125    "                                                                                                              ",
126    "                                                                                                              ",
127    "                                                                                                              ",
128    "                                                                                                              ",
129    "                                        o                                                                     ",
130    "                                                                                                              ",
131    "                                        x                                                                     ",
132    "                                        x                                                                     ",
133    "                                        x                                                                     ",
134    "                                        x                                                                     ",
135    "                                       xxx                                                                    ",
136    "                                       x x                 !!!        !!!  xxx                                ",
137    "                                       x x                 !x!        !x!                                     ",
138    "                                     xxx xxx                x          x                                      ",
139    "                                      x   x                 x   oooo   x       xxx                            ",
140    "                                      x   x                 x          x      x!!!x                           ",
141    "                                      x   x                 xxxxxxxxxxxx       xxx                            ",
142    "                                     xx   xx      x   x      x                                                ",
143    "                                      x   xxxxxxxxx   xxxxxxxx              x x                               ",
144    "                                      x   x           x                    x!!!x                              ",
145    "                                      x   x           x                     xxx                               ",
146    "                                     xx   xx          x                                                       ",
147    "                                      x   x= = = =    x            xxx                                        ",
148    "                                      x   x           x           x!!!x                                       ",
149    "                                      x   x    = = = =x     o      xxx       xxx                              ",
150    "                                     xx   xx          x                     x!!!x                             ",
151    "                              o   o   x   x           x     x                xxv        xxx                   ",
152    "                                      x   x           x              x                 x!!!x                  ",
153    "                             xxx xxx xxx xxx     o o  x!!!!!!!!!!!!!!x                   vx                   ",
154    "                             x xxx x x xxx x          x!!!!!!!!!!!!!!x                                        ",
155    "                             x             x   xxxxxxxxxxxxxxxxxxxxxxx                                        ",
156    "                             xx           xx                                         xxx                      ",
157    "  xxx                         x     x     x                                         x!!!x                xxx  ",
158    "  x x                         x    xxx    x                                          xxx                 x x  ",
159    "  x                           x    xxx    xxxxxxx                        xxxxx                             x  ",
160    "  x                           x           x                              x   x                             x  ",
161    "  x                           xx          x                              x x x                             x  ",
162    "  x                                       x       |xxxx|    |xxxx|     xxx xxx                             x  ",
163    "  x                xxx             o o    x                              x         xxx                     x  ",
164    "  x               xxxxx       xx          x                             xxx       x!!!x          x         x  ",
165    "  x               oxxxo       x    xxx    x                             x x        xxx          xxx        x  ",
166    "  x                xxx        xxxxxxxxxxxxx  x oo x    x oo x    x oo  xx xx                    xxx        x  ",
167    "  x      @          x         x           x!!x    x!!!!x    x!!!!x    xx   xx                    x         x  ",
168    "  xxxxxxxxxxxxxxxxxxxxxxxxxxxxx           xxxxxxxxxxxxxxxxxxxxxxxxxxxxx     xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx  ",
169    "                                                                                                              ",
170    "                                                                                                              "],
171   ["                                                                                                  xxx x       ",
172    "                                                                                                      x       ",
173    "                                                                                                  xxxxx       ",
174    "                                                                                                  x           ",
175    "                                                                                                  x xxx       ",
176    "                          o                                                                       x x x       ",
177    "                                                                                             o o oxxx x       ",
178    "                   xxx                                                                                x       ",
179    "       !  o  !                                                xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx       ",
180    "       x     x                                                x   x x   x x   x x   x x   x x   x x           ",
181    "       x= o  x            x                                   xxx x xxx x xxx x xxx x xxx x xxx x xxxxx       ",
182    "       x     x                                                  x x   x x   x x   x x   x x   x x     x       ",
183    "       !  o  !            o                                  xxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxxxx       ",
184    "                                                                                                              ",
185    "          o              xxx                              xx                                                  ",
186    "                                                                                                              ",
187    "                                                                                                              ",
188    "                                                      xx                                                      ",
189    "                   xxx         xxx                                                                            ",
190    "                                                                                                              ",
191    "                          o                                                     x      x                      ",
192    "                                                          xx     xx                                           ",
193    "             xxx         xxx         xxx                                 x                  x                 ",
194    "                                                                                                              ",
195    "                                                                 ||                                           ",
196    "  xxxxxxxxxxx                                                                                                 ",
197    "  x         x o xxxxxxxxx o xxxxxxxxx o xx                                                x                   ",
198    "  x         x   x       x   x       x   x                 ||                  x     x                         ",
199    "  x  @      xxxxx   o   xxxxx   o   xxxxx                                                                     ",
200    "  xxxxxxx                                     xxxxx       xx     xx     xxx                                   ",
201    "        x=                  =                =x   x                     xxx                                   ",
202    "        xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx   x!!!!!!!!!!!!!!!!!!!!!xxx!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
203    "                                                  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
204    "                                                                                                              "]
205 ];
206  
207 // assumes the plan is valid (add validation for production)
208 function level(plan) {
209   this.width = plan[0].length;
210   this.height = plan.length;
211   // array of arrays, each position containing null or a character
212   this.grid = [];
213   // contains all of the dynamic objects (lava, coin or player),
214   // along with their position and state
215   this.actors = [];
216   
217   for (var y = 0; y < this.height; y++) {
218     var line = plan[y], gridline = [];
219     for (var x = 0; x < this.width; x++) {
220       var ch = line[x], fieldtype = null;
221       var actor = actorchars[ch];
222       if (actor)
223         // this constructs the referenced moving object in
224         // actorchars and pushes it to the actors array
225         this.actors.push(new actor(new vector(x, y), ch));
226       else if (ch == 'x')
227         // wall
228         fieldtype = 'wall';
229       else if (ch == '!')
230         // stationary lava
231         fieldtype = 'lava';
232       gridline.push(fieldtype);
233     }
234     this.grid.push(gridline);
235   }
236   // find the player actor
237   this.player = this.actors.filter(function(actor) {
238     return actor.type == 'player';
239   })[0];
240   // track whether the player has won or lost;
241   // finishdelay keeps the level active for a brief period of time
242   this.status = this.finishdelay = null;
243 }
244 // figure out if the level is finished
245 level.prototype.isfinished = function() {
246   return this.status != null && this.finishdelay < 0;
247 };
248 // figure out the collision area of an actor
249 level.prototype.obstacleat = function(pos, size) {
250   var xstart = math.floor(pos.x);
251   var xend = math.ceil(pos.x + size.x);
252   var ystart = math.floor(pos.y);
253   var yend = math.ceil(pos.y + size.y);
254   
255   // the upper and side bounds of the level return a wall
256   if (xstart < 0 || xend > this.width || ystart < 0)
257     return 'wall';
258   // the bottom bound returns lava
259   if (yend > this.height)
260     return 'lava';
261   // check what's on the grid around the collision box
262   for (var y = ystart; y < yend; y++) {
263     for (var x = xstart; x < xend; x++) {
264       var fieldtype = this.grid[y][x];
265       // returns 'wall' or 'lava'
266       if (fieldtype) return fieldtype;
267     }
268   }
269 };
270 // track what actors overlap a given actor
271 level.prototype.actorat = function(actor) {
272   for (var i = 0; i < this.actors.length; i++) {
273     var other = this.actors[i];
274     if (other != actor &&
275         actor.pos.x + actor.size.x > other.pos.x &&
276         actor.pos.x < other.pos.x + other.size.x &&
277         actor.pos.y + actor.size.y > other.pos.y &&
278         actor.pos.y < other.pos.y + other.size.y)
279       return other;
280   }
281 };
282 // time increment for level.animate()
283 var maxstep = 0.05;
284 // animate the level
285 // step will be given in seconds, keys is an object that
286 // contains info about the arrow keys the player has pressed.
287 level.prototype.animate = function(step, keys) {
288   // used for the delay at the end of a game
289   if (this.status != null)
290     this.finishdelay -= step;
291   
292   while (step > 0) {
293     var thisstep = math.min(step, maxstep);
294     this.actors.foreach(function(actor) {
295       actor.act(thisstep, this, keys);
296     }, this);
297     step -= thisstep;
298   }
299 };
300 // handle collisions between actors
301 level.prototype.playertouched = function(type, actor) {
302   // lava's been touched
303   if (type == 'lava' && this.status == null) {
304     this.status = 'lost';
305     this.finishdelay = 1;
306   } else if (type == 'coin') { // a coin's been touched
307     // remove the coin that's been collected from actors array
308     this.actors = this.actors.filter(function(other) {
309       return other != actor;
310     });
311     // no more coins = you've won
312     if (!this.actors.some(function(actor) {
313       return actor.type == 'coin';
314     })) {
315       this.status = 'won';
316       this.finishdelay = 1;
317     }
318   }
319 }
320  
321 var actorchars = {
322   '@': player,
323   'o': coin,
324   '=': lava, '|': lava, 'v': lava
325 };
326  
327 // vector stores the position and size of an actor
328 function vector(x, y) {
329   this.x = x; this.y = y;
330 }
331 vector.prototype.plus = function(other) {
332   return new vector(this.x + other.x, this.y + other.y);
333 }
334 vector.prototype.times = function(factor) {
335   return new vector(this.x * factor, this.y * factor);
336 }
337  
338 // player constructor
339 function player(pos) {
340   // this properly aligns the bottom of the player
341   // to the square below (adjusts for player height)
342   this.pos = pos.plus(new vector(0, -0.5));
343   this.size = new vector(0.8, 1.5);
344   this.speed = new vector(0, 0);
345 }
346 player.prototype.type = 'player';
347 // x and y movement are handled independently because
348 // a wall shouldn't stop the up and down motion of jumping
349 // and a floor shouldn't stop side to side movement
350 var playerxspeed = 7;
351 player.prototype.movex = function(step, level, keys) {
352   this.speed.x = 0;
353   if (keys.left) this.speed.x -= playerxspeed;
354   if (keys.right) this.speed.x += playerxspeed;
355   
356   var motion = new vector(this.speed.x * step, 0);
357   var newpos = this.pos.plus(motion);
358   var obstacle = level.obstacleat(newpos, this.size);
359   if (obstacle)
360     level.playertouched(obstacle);
361   else
362     this.pos = newpos;
363 };
364 var gravity = 30;
365 var jumpspeed = 17;
366 player.prototype.movey = function(step, level, keys) {
367   this.speed.y += step * gravity;
368   var motion = new vector(0, this.speed.y * step);
369   var newpos = this.pos.plus(motion);
370   var obstacle = level.obstacleat(newpos, this.size);
371   if (obstacle) {
372     level.playertouched(obstacle);
373     if (keys.up && this.speed.y > 0)
374       this.speed.y = -jumpspeed;
375     else
376       this.speed.y = 0;
377   } else {
378     this.pos = newpos;
379   }
380 };
381 player.prototype.act = function(step, level, keys) {
382   this.movex(step, level, keys);
383   this.movey(step, level, keys);
384   
385   var otheractor = level.actorat(this);
386   if (otheractor)
387     level.playertouched(otheractor.type, otheractor);
388   
389   // losing animation
390   if (level.status == 'lost') {
391     this.pos.y += step;
392     this.size.y -=step;
393   }
394 };
395  
396 // lava constructor
397 function lava(pos, ch) {
398   this.pos = pos;
399   this.size = new vector(1, 1);
400   if (ch == "=") {
401     // i'm guessing that speed will be added to this.pos
402     // in a moving method added later
403     this.speed = new vector(2, 0);
404   } else if (ch == '|') {
405     this.speed = new vector(0, 2);
406   } else if (ch == 'v') {
407     this.speed = new vector(0, 3);
408     this.repeatpos = pos;
409   }
410 }
411 lava.prototype.type = 'lava';
412 // action
413 lava.prototype.act = function(step, level) {
414   var newpos = this.pos.plus(this.speed.times(step));
415   if (!level.obstacleat(newpos, this.size))
416     this.pos = newpos;
417   else if (this.repeatpos)
418     this.pos = this.repeatpos;
419   else
420     this.speed = this.speed.times(-1);
421 };
422  
423 // coin constructor
424 function coin(pos) {
425   this.basepos = this.pos = pos.plus(new vector(0.2, 0.1));
426   this.size = new vector(0.6, 0.6);
427   this.wobble = math.random() * math.pi * 2;
428 }
429 coin.prototype.type = 'coin';
430 var wobblespeed = 8, wobbledist = 0.07;
431 // action
432 coin.prototype.act = function(step) {
433   this.wobble += step * wobblespeed;
434   var wobblepos = math.sin(this.wobble) * wobbledist;
435   this.pos = this.basepos.plus(new vector(0, wobblepos));
436 };
437  
438 // helper function that creates an element
439 // and gives it a class
440 function elt(name, classname) {
441   var elt = document.createelement(name);
442   if (classname) elt.classname = classname;
443   return elt;
444 }
445  
446 // tracking keypresses for player movement
447 var arrowcodes = {37: 'left', 38: 'up', 39: 'right'};
448  
449 function trackkeys(codes) {
450   var pressed = object.create(null);
451   function handler(event) {
452     if (codes.hasownproperty(event.keycode)) {
453       var down = event.type == 'keydown';
454       pressed[codes[event.keycode]] = down;
455       event.preventdefault();
456     }
457   }
458   addeventlistener('keydown', handler);
459   addeventlistener('keyup', handler);
460   
461   pressed.unregister = function() {
462     removeeventlistener('keydown', handler);
463     removeeventlistener('keyup', handler);
464   };
465   
466   return pressed;
467 }
468  
469 // run the animation
470 function runanimation(framefunc) {
471   var lasttime = null;
472   function frame(time) {
473     var stop = false;
474     if (lasttime != null) {
475       var timestep = math.min(time - lasttime, 100) / 1000;
476       stop = framefunc(timestep) === false;
477     }
478     lasttime = time;
479     if (!stop)
480       requestanimationframe(frame);
481   }
482   requestanimationframe(frame);
483 }
484  
485 // run the level
486 var arrows = trackkeys(arrowcodes);
487  
488 function runlevel(level, display, andthen) {
489   var display = new display(document.body, level);
490   // used for storing pause state of the game
491   var running = 'yes';
492   
493   function handlekey(event) {
494     if (event.keycode == 27) {
495       if (running == 'no') {
496         running = 'yes';
497         runanimation(animation);
498       } else if (running == 'pausing') {
499         running = 'yes';
500       } else if (running == 'yes') {
501         running = 'pausing';
502       }
503     }
504   }
505   addeventlistener('keydown', handlekey);
506   
507   function animation(step) {
508     if (running == 'pausing') {
509       running = 'no';
510       return false;
511     }
512     
513     level.animate(step, arrows);
514     display.drawframe(step);
515     if (level.isfinished()) {
516       display.clear();
517       // remove the watch on the esc key 
518       //removeeventlistener('keydown', handlekey);
519       // unregister the arrow key listeners
520       //arrows.unregister();
521       if (andthen)
522         andthen(level.status);
523       return false;
524     }
525   }
526   
527   runanimation(animation);
528 }
529  
530 // run the game
531 function rungame(plans, display) {
532   var lives = 3;
533   var livesspan = document.getelementbyid('lives');
534   var gamestatus = document.getelementbyid('status');
535   
536   function startlevel(n) {
537     livesspan.textcontent = lives;
538     runlevel(new level(plans[n]), display, function(status) {
539       if (status == 'lost') {
540         lives--;
541         if (lives == 0) {
542           gamestatus.textcontent = 'game over';
543           console.log('game over');
544         }
545         else 
546           startlevel(n);
547       }
548       else if (n < plans.length - 1)
549         startlevel(n + 1);
550       else
551         console.log('you win!');
552     });
553   }
554   startlevel(0);
555 }
556  
557  
558 // domdisplay uses the dom to draw the program out
559 function domdisplay(parent, level) {
560   this.wrap = parent.appendchild(elt('div', 'game'));
561   this.level = level;
562   
563   // background is drawn only once
564   this.wrap.appendchild(this.drawbackground());
565   // the actorlayer is animated in the drawframe() method
566   this.actorlayer = null;
567   this.drawframe();
568 }
569 // set the scale of 1 grid unit
570 var scale = 20;
571 // draw the background
572 domdisplay.prototype.drawbackground = function() {
573   var table = elt('table', 'background');
574   table.style.width = this.level.width * scale + 'px';
575   this.level.grid.foreach(function(row) {
576     var rowelt = table.appendchild(elt('tr'));
577     rowelt.style.height = scale + 'px';
578     row.foreach(function(type) {
579       rowelt.appendchild(elt('td', type));
580     });
581   });
582   return table;
583 };
584 // draw the actors
585 domdisplay.prototype.drawactors = function() {
586   var wrap = elt('div');
587   this.level.actors.foreach(function(actor) {
588     var rect = wrap.appendchild(elt('div', 'actor ' + actor.type));
589     rect.style.width  = actor.size.x * scale + 'px';
590     rect.style.height = actor.size.y * scale + 'px';
591     rect.style.left   = actor.pos.x * scale + 'px';
592     rect.style.top    = actor.pos.y * scale + 'px';
593   });
594   return wrap;
595 };
596 // redraw the actors
597 domdisplay.prototype.drawframe = function() {
598   if (this.actorlayer)
599     this.wrap.removechild(this.actorlayer);
600   this.actorlayer = this.wrap.appendchild(this.drawactors());
601   // the status class is used to style the player based on
602   // the state of the game (won or lost)
603   this.wrap.classname = 'game ' + (this.level.status || '');
604   this.scrollplayerintoview();
605 };
606 // make sure the player's always on screen
607 domdisplay.prototype.scrollplayerintoview = function() {
608   var width = this.wrap.clientwidth;
609   var height = this.wrap.clientheight;
610   var margin = width / 3;
611   
612   // the viewport
613   var left = this.wrap.scrollleft, right = left + width;
614   var top = this.wrap.scrolltop, bottom = top + height;
615   
616   // center makes use of the vector methods defined earlier
617   var player = this.level.player;
618   var center = player.pos.plus(player.size.times(0.5))
619                   .times(scale);
620   
621   if (center.x < left + margin)
622     this.wrap.scrollleft = center.x - margin;
623   else if (center.x > right - margin)
624     this.wrap.scrollleft = center.x + margin - width;
625   if (center.y < top + margin)
626     this.wrap.scrolltop = center.y - margin;
627   else if (center.y > bottom - margin)
628     this.wrap.scrolltop = center.y + margin - height;
629 }
630 // clear the level
631 domdisplay.prototype.clear = function() {
632   this.wrap.parentnode.removechild(this.wrap);
633 };
634  
635 // canvas api helper function
636 function fliphorizontally(context, around) {
637   context.translate(around, 0);
638   context.scale(-1, 1);
639   context.translate(-around, 0);
640 }
641 // use canvas api to draw game
642 function canvasdisplay(parent, level) {
643   // set up the canvas element
644   this.canvas = document.createelement('canvas');
645   this.canvas.width = math.min(1000, level.width * scale);
646   this.canvas.height = math.min(1000, level.height * scale);
647   this.canvas.style.display = 'block';
648   this.canvas.style.margin = '200px auto 0';
649   parent.appendchild(this.canvas);
650   this.cx = this.canvas.getcontext('2d');
651   
652   this.level = level;
653   // uses the step size passed to drawframe()
654   this.animationtime = 0;
655   this.flipplayer = false;
656   
657   this.viewport = {
658     left: 0,
659     top: 0,
660     width: this.canvas.width / scale,
661     height: this.canvas.height / scale
662   };
663   
664   this.drawframe(0);
665 }
666 canvasdisplay.prototype.clear = function() {
667   this.canvas.parentnode.removechild(this.canvas);
668 };
669 // draw the frame
670 canvasdisplay.prototype.drawframe = function(step) {
671   this.animationtime += step;
672   
673   // update the current player position for the viewport
674   this.updateviewport();
675   // clear current frame
676   this.cleardisplay();
677   // draw the background
678   this.drawbackground();
679   // draw the actors
680   this.drawactors();
681 };
682 // scrolls the viewport depending on the player position
683 canvasdisplay.prototype.updateviewport = function() {
684   var view = this.viewport, margin = view.width / 3;
685   var player = this.level.player;
686   var center = player.pos.plus(player.size.times(0.5));
687   
688   // compare the center.x of player to the viewport
689   // player is less than the left of the viewport plus margin
690   if (center.x < view.left + margin)
691     // scroll left until less than 0
692     view.left = math.max(center.x - margin, 0);
693   // player is further right than the right of the viewport plus margin
694   else if (center.x > view.left + view.width - margin)
695     // scroll right until greater than the edge of the level
696     view.left = math.min(center.x + margin - view.width,
697                         this.level.width - view.width);
698   if (center.y < view.top + margin)
699     view.top = math.max(center.y - margin, 0);
700   else if (center.y > view.top + view.height - margin)
701     view.top = math.min(center.y + margin - view.height,
702                        this.level.height - view.height);
703 };
704 canvasdisplay.prototype.cleardisplay = function() {
705   if (this.level.status == 'won')
706     this.cx.fillstyle = 'rgb(68, 191, 255)';
707   else if (this.level.status == 'lost')
708     this.cx.fillstyle = 'rgb(44, 136, 214)';
709   else
710     this.cx.fillstyle = 'rgb(52, 166, 251)';
711   this.cx.fillrect(0, 0,
712                   this.canvas.width, this.canvas.height);
713 };
714 var othersprites = document.createelement('img');
715 othersprites.src = 'http://eloquentjavascript.net/img/sprites.png';
716 // draw the background
717 canvasdisplay.prototype.drawbackground = function() {
718   var view = this.viewport;
719   var xstart = math.floor(view.left);
720   var xend = math.ceil(view.left + view.width);
721   var ystart = math.floor(view.top);
722   var yend = math.ceil(view.top + view.height);
723   
724   for (var y = ystart; y < yend; y++) {
725     for (var x = xstart; x < xend; x++) {
726       var tile = this.level.grid[y][x];
727       if (tile == null) continue;
728       var screenx = (x - view.left) * scale;
729       var screeny = (y - view.top) * scale;
730       var tilex = tile == 'lava' ? scale : 0;
731       this.cx.drawimage(othersprites,
732                        tilex,   0,       scale, scale,
733                        screenx, screeny, scale, scale);
734     }
735   }
736 };
737 // draw the player (called by drawactors())
738 var playersprites = document.createelement('img');
739 playersprites.src = 'http://eloquentjavascript.net/img/player.png';
740 var playerxoverlap = 4;
741 canvasdisplay.prototype.drawplayer = function(x, y, width, height) {
742   var sprite = 8, player = this.level.player;
743   width += playerxoverlap * 2;
744   x -= playerxoverlap;
745   if (player.speed.x != 0)
746     this.flipplayer = player.speed.x < 0;
747   
748   if (player.speed.y != 0)
749     sprite = 9;
750   else if (player.speed.x != 0)
751     sprite = math.floor(this.animationtime * 12) % 8;
752   
753   this.cx.save();
754   if (this.flipplayer)
755     fliphorizontally(this.cx, x + width / 2);
756   
757   this.cx.drawimage(playersprites,
758                    sprite * width, 0, width, height,
759                    x,              y, width, height);
760   this.cx.restore();
761 }
762 // draw the actors
763 canvasdisplay.prototype.drawactors = function() {
764   this.level.actors.foreach(function(actor) {
765     var width = actor.size.x * scale;
766     var height = actor.size.y * scale;
767     var x = (actor.pos.x - this.viewport.left) * scale;
768     var y = (actor.pos.y - this.viewport.top) * scale;
769     if (actor.type == 'player') {
770       this.drawplayer(x, y, width, height);
771     } else {
772       var tilex = (actor.type == 'coin' ? 2 : 1) * scale;
773       this.cx.drawimage(othersprites,
774                        tilex, 0, width, height,
775                        x,     y, width, height);
776     }
777   }, this);
778 };
779  
780  
781 // run game with domdisplay
782 // rungame(game_levels, domdisplay);
783  
784 // run game with canvasdisplay
785 rungame(game_levels, canvasdisplay);
786 </script>
787  
788 </body>
789 </html>