Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. You can use the CSS from another Pen by using it's URL and the proper URL extention.

+ add another resource

JavaScript

Babel includes JSX processing.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Packages

Add Packages

Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.

Behavior

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                body
  #wrapper
    #game
    .buttons
      h2 Switch Players 
        i(class='fa fa-caret-down')
      a(id='player1' class='player active') player 1
      a(id='player2' class='player') player 2
  
  #fi(style="display:none; text-align:center; position:absolute; bottom:15px; right:15px; width:280px; font-family:'Lato', arial, helvetica; background:rgba(255,255,255,0.3); padding:8px 15px;" )
    P <strong>Like Indie Games? Got $5?</strong><br><a href="https://www.fiverr.com/ebrewe/build-a-simple-game?display_share=true" target="_blank" style="display:block; padding:5px 8px; color:white; background:#00b22d; font-weight:bold; text-decoration:none!important; text-align:center; border-bottom:3px solid #00920d; margin:0.5em 0;">Find me on Fiverr.com</a> to see what those two things have in common! 
              
            
!

CSS

              
                .clearfix {
  zoom: 1;
	&:before, &:after { content: ""; display: table; }
	&:after { clear: both; }
}
@mixin css-gradient($from: #dfdfdf, $to: #f8f8f8) {
	background-color: $to;
	background-image: -webkit-gradient(linear, left top, left bottom, from($from), to($to));
	background-image: -webkit-linear-gradient(top, $from, $to);
	background-image: -moz-linear-gradient(top, $from, $to);
	background-image: -o-linear-gradient(top, $from, $to);
	background-image: linear-gradient(to bottom, $from, $to);
}

//colours
$black: #312736;
$red: #d4838f;
$greyred: #d6abb1;
$green: #63b789;
$grey: #d9d9d9;
$blue: #c4ffeb;

 
* {box-sizing:border-box; }

body{
  display:block; 
  background:#999;
}

#wrapper {
  display:block;
  width:90%;
  height:auto;
  margin:0 auto; 
}

.buttons {
  display:block;
  font-family:arial, helvetica, sans-serif; 
  padding:20px; 
  border-radius:4px; 
  border:1px solid darken($grey, 40%);
  position:absolute;
  bottom:20px; 
  left:20px; 
  z-index:99; 
  
  h2 {
    font-weight:700;
    font-size:18px; 
    margin:0 0 10px; 
    color:#282828; 
  }
  
  a {
    display:block;
    float:left;
    border:1px solid darken($grey, 39%); 
    padding:10px 15px;
    border-radius:3px; 
    background:$grey;
    color:#3d3d3d; 
    margin-right:5px; 
    cursor:pointer; 
    &:hover {
      background:darken($grey, 13%);  
    }
    &:active{
      box-shadow:inset 0 2px 1px rgba(0,0,0,0.5);  
    }
    &.active {
      background:$green; 
      border-color:darken($green, 27%); 
      color: lighten($green, 40%); 
    }
  }
  
}
              
            
!

JS

              
                ###
~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~
~ Main game class
~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~
###

class Game

  constructor:(@container, @tileSize, {viewWidth, viewHeight, scale, iso} = {}) ->
    
    viewWidth ?= 600
    viewHeight ?= 400
    scale ?= 1
    iso ?= false
  
    @viewWidth = viewWidth
    @viewHeight = viewHeight 
    @scale = scale
    @iso = iso
    
  run: ->
    @setup()
    @then = Date.now()
    setInterval @tick, 30
    
    
  setup: ->
    @world = new World @container, @tileSize, @viewWidth, @viewHeight, @scale, @iso
    @inputHandler = new InputHandler( @world )
    
  update:(modifier) ->
    @inputHandler.update(modifier)
    @world.update()
  
  tick: =>
    now = Date.now()
    delta = now - @lastUpdate
    @lastUpdate = now
    @lastElapsed = delta
    @update(delta / 1000)
    @world.draw()

  
###
~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~
~The World Class
~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~
###

class World
  
  constructor: (@container, tileSize, @viewWidth, @viewHeight, @scale, @iso) ->
    @debug = false
    
    @tileWidth = if @iso then tileSize * 2 * @scale else tileSize * @scale
    @tileHeight = tileSize * @scale
    
    @ctx = @createCanvas()
    @sprites = []
    @scrollX = 0
    @scrollY = 0
    @quickScroll = false
    @collisions = []
    @collisionIndex = {}
    @controls = []
    @inventory = []
    
  createCanvas: ->
    container = document.getElementById @container
    canvas = document.createElement('canvas')
    canvas.setAttribute('id', 'eNgine_canvas')
    canvas.width = @viewWidth
    canvas.height = @viewHeight
    container.appendChild canvas
    
    @canvas = canvas
    @canvas.getContext('2d')
    
  createWorld: (@map) ->
    ###
    create a collision map based on the map
    switch all unwalkable tiles to 1s on cmap
    for pathfinding
    ###
    
    @cMap = @map
    for row in @cMap
      for tile in row
        if row[tile] is not 0
          row[tile] = 1
          
    @createBackground( @map )
    @createPFGrid( @cMap )
    
  createBackground: (map) =>
    @background = new Background this, map
    
  createPFGrid: (cMap )->
    @grid = new PF.Grid( cMap[0].length, cMap.length, cMap)
	  #@finder = new PF.AStarFinder()
    @finder = new PF.BreadthFirstFinder()
    
  update: (modifier) ->
    if @background
      for tile in @background.tiles
        tile.update()
    @sortSprites @sprites
    sprite.update() for sprite in @sprites
    
    @collisionCheck(@sprites)
    
    
    if @player.rX < 200
      @scrollX -= if @quickScroll then @tileWidth else 3
    if @player.rX > @viewWidth - 200
      @scrollX += if @quickScroll then @tileWidth else 3
    if @player.rY < 50
      @scrollY -= if @quickScroll then @tileHeight else 3
    if @player.rY > @viewHeight - 50
      @scrollY += if @quickScroll then @tileHeight else 3
    
    if @player.rX > 200 and @player.rX <= (@viewWidth - 200) and @player.rY > 50 and @player.rY <= (@viewHeight - 50)
      @quickScroll = false
    
  sortSprites: (sprites) ->
    sprites = sprites.sort (a,b)->
      return if a.z > b.z then 1 else - 1
    
  collisionCheck: (sprites)->
    @collisions = []
    @collisionIndex = {}
    for spriteA in sprites
      if spriteA.collides
      
        #check this sprite against all other sprites
        for spriteB in sprites
             if spriteB != spriteA and spriteB.collides
               
               #check for collision between sprites
               ###
               if less than half a tile height above
               or less than half a tile height below
               and less than half a tile width beside
               ###
               colY = Math.abs spriteB.y - spriteA.y
               colX = Math.abs spriteB.x - spriteA.x
               if colY < @tileHeight / 2 and colX < @tileWidth/ 2
                 @collisions.push spriteA
                 @collisions.push spriteB
                 @collisionIndex[spriteA.name] = spriteB
    
  draw: ->
    @ctx.clearRect 0, 0, @viewWidth, @viewHeight
    if @background    
      for tile in @background.tiles
        tile.draw()
    sprite.draw() for sprite in @sprites


          
###
~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~
~The Input Handler Class
~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~
###

class InputHandler
  
  keysDown : {}
  clicked: false
  
  constructor: (@world) ->
    @bindMouse()  
  
  bindMouse: =>
    that = this
    @world.canvas.addEventListener('mousemove', (evt)->
      that.mousePos = that.getMousePos(evt)
    )
    
  getMousePos:(evt) ->
    rect = @world.canvas.getBoundingClientRect()
    { x: evt.clientX - rect.left, y: evt.clientY - rect.top }
    

  update: (modifier) ->
    
    ### 
    clear previous flags
    ###
    
    for i in [0 .. @world.background.tiles.length]
      if @world.background.tiles[i]
        @world.background.tiles[i].clearFlags 'hover'
    ###
    main input update
    ###
    if @world.background and @world.background.ready and @mousePos and @mousePos.x > 0 and @mousePos.x < @world.viewWidth and @mousePos.y > 0 and @mousePos.y < @world.viewHeight
      
      if @world.iso
        tileX = Math.floor ( (@mousePos.x + @world.scrollX)  / @world.tileWidth ) + ( (@mousePos.y + @world.scrollY)  / @world.tileHeight) - .5 
        tileY = Math.floor ( (@mousePos.y + @world.scrollY) / @world.tileHeight ) - ( (@mousePos.x + @world.scrollX) / @world.tileWidth) + .5
      else
        tileX = Math.floor (@mousePos.x + @world.scrollX) / @world.tileWidth
        tileY = Math.floor (@mousePos.y + @world.scrollY) / @world.tileHeight
      
     
           
      if @world.background.mapTiles[tileY] 
        if @world.background.mapTiles[tileY][tileX]
          theTile = @world.background.mapTiles[tileY][tileX]  
          if theTile.walkable
            theTile.setFlags('hover') 
            
            if @clicked
              onPlayer = false
                
              for tile in @world.background.tiles
                tile.clearFlags 'selected'
                tile.clearFlags 'path'
              #if @world.player.path
                #for tile in @world.player.path
                  #@world.background.mapTiles[tile[1]][tile[0]].clearFlags 'path'
              theTile.setFlags 'selected'
              
              ###
              Pathfinding
              ###
              pcoords = @world.player.getTile()
              goalX = theTile.rX
              goalY = theTile.rY
              
              
              for sprite in @world.sprites
                if sprite.entType and sprite.entType == 'player'
                    if sprite.myTile.rX == goalX and sprite.myTile.rY == goalY
                        #occupado
                        onPlayer = true
                        
              if onPlayer
                @clicked = false
                return false
                        
              gridClone = @clone @world.grid
              path = @world.finder.findPath pcoords.x, pcoords.y, tileX, tileY, gridClone
              for tile in path
                @world.background.mapTiles[tile[1]][tile[0]].setFlags 'path'
              if path and path[0]            
                @world.background.mapTiles[ path[0][1] ][path[0][0]].clearFlags 'path'
                @world.player.walkPath path
      
    ###
    clear click
    ###
    @clicked = false
    
  clone: (obj) ->
    if not obj? or typeof obj isnt 'object'
      return obj
	
    if obj instanceof Date
      return new Date(obj.getTime()) 
	
    if obj instanceof RegExp
      flags = ''
      flags += 'g' if obj.global?
      flags += 'i' if obj.ignoreCase?
      flags += 'm' if obj.multiline?
      flags += 'y' if obj.sticky?
      return new RegExp(obj.source, flags) 
	
    newInstance = new obj.constructor()
	
    for key of obj
      newInstance[key] = @clone obj[key]
	
    newInstance
	  
###
~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~
~The Sprite Class
~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~
###
class SpriteImage

  ready: false
  
  constructor:(@url = 'images/spritesheet.png', world, sprite) ->
    image = new Image
    #image = document.createElement('img')
    image.src = @url
    @image = image
    @image.onload= => 
      @ready = true
      #if world.debug
        #console.log 'created a ' + sprite

class Sprite

  x: 0 #world-relative x
  y: 0 #world-relative y
  w: 0
  h: 0
  z: 0
  zIndex: 0
  name: 'sprite'
  collides: false
  ready: false
  image: false
  frame:0
  animationFrames: 0
  
  constructor: (@world, url) ->
    if url
      @image = new SpriteImage url, @world, @name
    console.log @name, @world if @world.debug
    @rX = @x
    @rY = @y
    @z = @rY
    @world.sprites.push this unless @name is 'tile' 
    
  setAnimationFrames: (frames) ->
    @animationFrames = frames
    
  update: (modifier) ->
    @rX = @x - @world.scrollX
    @rY = @y - @world.scrollY
    
    @z = @rY + @zIndex
    
  draw: ->
    if @image.image and @image.ready 
       sx = ( @w * @frame )
       w = @w 
       h =  @h 
       sy = 0
       try
         @world.ctx.drawImage( @image.image, sx, sy, w, h, @rX , @rY, @w * @world.scale, @h * @world.scale )
       catch error
         console.log  @image.image, 0,0, 0, 0, @rX , @rY, @w, @h
         console.log 'effin ' + error
         
  drawFrame: (frame) ->
    sx = 0 
    sy = 0
    @world.ctx.drawImage( @image, sx, sy, @rX, @rY, @w, @h )
    
      
###
~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~
~The Background Class
~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~
###

class Background 

  constructor: (@world, map) ->
    @x = 0
    @y = 0
    @w = 0
    @h= 0
    @rX = @x
    @rY = @y
    @tiles = []
    @mapTiles =[]
    @map = map
    
    for rIndex, row of @map
      @mapTiles[rIndex] = []
      #TODO go backwards to render in sequence
      for i in [row.length-1..0] by -1
        cIndex = i
        column = row[cIndex]       
        w= @world.tileWidth
        h= @world.tileHeight
        x = cIndex
        y = rIndex
        tileNo = [cIndex, rIndex] 
        walkable = true
        if column != 0 then walkable = false
        
        if @world.iso
          isoCoords = @twoDToIso x, y, w, h 
          tile = new DrawnTile @world, isoCoords.x, isoCoords.y, @world.tileWidth, @world.tileHeight, column, tileNo, walkable
        else
          x = cIndex * w
          y = rIndex * h
          tile = new Tile @world, x, y, @world.tileWidth, @world.tileHeight, 'tile', tileNo, walkable
          
        @tiles.push tile
        @mapTiles[rIndex][cIndex] = tile 
        
        
    @ready = true
    console.log @tiles if @world.debug
        
  twoDToIso: (x, y, w, h)->
    isoX = (x * w / 2) - (y * w / 2)
    isoY = (y * h / 2) + (x * h / 2)
    {x: isoX, y: isoY}
    
  backgroundSize: ->
    
        
  update: (modifier) ->
    super()  
  
 
###
~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~
~The Tile Class
~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~
###

class Tile extends Sprite
  
  constructor: (@world, @x, @y, @w, @h, @type = 0, @tileNo = [0, 0], @walkable=true)->
    # super @world, 'images/gameTile.png'
    super()
    @name = 'tile'
    # image = @getType()
    @color = 'rgba(0,0,255,' + (parseInt(@tileNo[0]) / 10) + ')'
    @flags = {}
    @tileFrame = @getTileFrame()
    
  update: (modifier)->
    @rX = @x - @world.scrollX
    @rY = @y - @world.scrollY
    
    
      
    ###
    different tiles
    ###
    @frame = @tileFrame
    
    if @flags.hover
      @frame = 1
    if @flags.selected
      @frame = 2
    if @flags.path
      @frame = 3
    
  draw: (frame = 0)->
    #@world.ctx.fillStyle = '#d6abb1'
    #@world.ctx.fillRect @x, @y, @w, @h
    if @world.debug
      @world.ctx.strokeStyle = @color
      @world.ctx.strokeRect @rX, @rY, @w, @h
      
    
    if @image.ready
    
       sx = ( @w * @frame ) 
       sy = 0
       @world.ctx.drawImage( @image.image, sx / @world.scale, sy, @w / @world.scale, @h / @world.scale, @rX , @rY, @w, @h )
      
    
  setFlags: (flag)->
    @flags[flag] = true
  
  clearFlags: (flag)->
    @flags[flag] = false
  
  
     
  getTileFrame: ->
    tileFrames=
      0: 0,
      1: 0,
      2: 4,
      3: 5,
      4: 6,
      5: 7
      
    tileFrames[@type]
      
  getType: ->
    tileTypes= 
      'tile': 'images/gameTile.png',
      'isoTile': 'images/gameTileIso.png',
      
     type = if @world.iso then 'isoTile' else 'tile'
     tileTypes[type]
     
class DrawnTile extends Tile
  colour: ''
  
  constructor: (@world, @x, @y, @w, @h, @type = 0, @tileNo = [0, 0], @walkable=true) ->
    super()
    @defaultColour = '#d6abb1'
    if @type is 1 then @defaultColour = 'rgba(0,0,0,0)'
    
    
  update: (modifier)->
  
    @rX = @x - @world.scrollX
    @rY = @y - @world.scrollY
    
    @colour = @defaultColour
    if @flags.path
      @colour = @getColour 'path'
    if @flags.hover
      @colour = @getColour 'hover'
    if @flags.selected
      @colour = @getColour 'selected'
    if @flags.occupied
      @colour = @getColour 'occupied'

  draw: ->
    @world.ctx.fillStyle = @colour
    @world.ctx.beginPath()
    @world.ctx.moveTo @rX + (@world.tileWidth / 2), @rY
    @world.ctx.lineTo @rX + @world.tileWidth, @rY + (@world.tileHeight / 2)
    @world.ctx.lineTo @rX + (@world.tileWidth / 2), @rY + @world.tileHeight
    @world.ctx.lineTo @rX, @rY + (@world.tileHeight / 2)
    @world.ctx.closePath()
    @world.ctx.fill()
    
    
  getColour: (flag) ->
    colours=
      hover: '#cd8791',
      selected: 'white',
      path:  '#f1d2d6',
      occupied: '#0000ff'
      
    colours[flag]
      
###
~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~
~The platform Class
~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~
###
class Platform extends Sprite

  name: 'platform'
  vx: 0
  vy: 0
  collides: true
  active: false
  
  constructor: (@world, @x, @y, @w, @h, @moving= false, @startPos = [], @endPos = [], @startGrid=[], @endGrid=[], speed = 1.5)->
    super()
    image = false
    @defaultColour = 'blue'
    @activeColour = 'yellow'
    @inMotion = false
    @speedY = speed
    @speedX = if @world.iso then speed * 2 else speed
    @direction = 1
    @waiting = false
    @startX = @startPos[0]
    @startY = @startPos[1]
    @endX = @endPos[0]
    @endY = @endPos[1]
    @zIndex = 0
    # super @world, image
    
  update: (modifier)=>
    if !@waiting and @active
      if @inMotion
        @move()
    
    
    @vx = 0 unless @x != @targetX
    @vy = 0 unless @y != @targetY
    
    @x += @vx
    @y += @vy
    
    
    @rX = @x - @world.scrollX
    @rY = @y - @world.scrollY
    
    
    
    @colour =  if @active then @activeColour else @defaultColour 
    @z = @rY + @zIndex
    
  startMoving: ->
    @inMotion = true
    
  stopMoving: -> 
    @inMotion = false
    
  changeDirection: (direction) =>
    that = this
    if @world.debug then console.log 'platform changing direction to ' + direction
    @stopMoving()
    @waiting = true
    setTimeout ()->
      that.waiting = false
      that.startMoving()
    , 2000
    @direction = direction
    
      
  move:  ->
  
    if @direction == false
      @targetX = @endX
      @targetY = @endY
      @targetGrid = @endGrid
    else
      @targetX = @startX
      @targetY = @startY
      @targetGrid = @startGrid
      
    
    
    deltaX = @x - @targetX
    deltaY = @y - @targetY    
    
    @world.grid.setWalkableAt(@startGrid[0], @startGrid[1], false)
    @world.grid.setWalkableAt(@endGrid[0], @endGrid[1], false)
    @world.background.mapTiles[@startGrid[1]][@startGrid[0]].walkable= false
    @world.background.mapTiles[@endGrid[1]][@endGrid[0]].walkable= false
    
    if deltaY == 0 and deltaX == 0
      @world.grid.setWalkableAt(@targetGrid[0], @targetGrid[1], true)
      @world.background.mapTiles[@targetGrid[1]][@targetGrid[0]].walkable= true
      return @changeDirection !@direction   
      
    
    if deltaY != 0
      @vy = if deltaY > 0 then -@speedY else @speedY
      
    if deltaX != 0
      @vx = if deltaX > 0 then -@speedX else @speedX
      
    
    
      
    
  draw: ->
    @world.ctx.fillStyle = @colour
    @world.ctx.beginPath()
    @world.ctx.moveTo @rX + (@world.tileWidth / 2), @rY
    @world.ctx.lineTo @rX + @world.tileWidth, @rY + (@world.tileHeight / 2)
    @world.ctx.lineTo @rX + (@world.tileWidth / 2), @rY + @world.tileHeight
    @world.ctx.lineTo @rX, @rY + (@world.tileHeight / 2)
    @world.ctx.closePath()
    @world.ctx.fill()
    
    if @world.debug
      @world.ctx.strokeStyle = 'black'
      @world.ctx.strokeRect @rX, @rY, @w, @h
  
###
~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~
~The Entity Class
~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~
###

class Entity extends Sprite
  speed:0
  vx: 0
  vy:0
  collides: true
  

  constructor: (@world, x, y, @w, @h, image, @speed = 0) ->
    super()
    @frame = 0
    @w *= @world.scale
    @h *= @world.scale
    @flip = false
    @speedX *= @world.scale
    @speedY *= @world.scale
    @defaultX = x
    @defaultY = y
    @x = x
    @y = y
    @path = false
 
    @zIndex = @world.tileHeight - 0.1
    # super  @world, image
  
  update: (modifier) =>
  
    @z = @rY + @zIndex
  
    @vx = 0 unless @nextX != @x
    @vy = 0 unless @nextY != @y
    
    
    
    if @vx == 0 and @vy == 0
      if @path and @path[2] and @world.background.mapTiles[@path[2][1]][@path[2][0]].walkable
        @path.shift()
        @walkPath @path
      else
        @path = []
        myTile = @getTile()
        @myTile =@world.background.mapTiles[myTile.y][myTile.x] 
        
    setVx = @vx
    setVy = @vy
        
    if @onPlatform 
      if @onPlatform.inMotion
        @x = @onPlatform.x
        @y = @onPlatform.y
        this.vx = 0
        this.vy = 0
           
    @x += @vx
    @y += @vy
    
      
    @rX = @x - @world.scrollX
    @rY = @y - @world.scrollY
    
    
    if @world.collisionIndex[this.name]
      collidesWith = @world.collisionIndex[this.name]
      if collidesWith.name == 'platform'
        @onPlatform = collidesWith
      else
        @onPlatform = false
    else
      @onPlatform = false
      
        
  animate: (frame, animation) ->
    frameIn = frame in animation
    frameIndex = animation.indexOf frame
    if frameIn
      @frame = frame 
    else
      @frame = animation[0]
      
  draw: ->  
    if @image.ready
      sx = ( @w * @frame ) 
      sy = 0
      @world.ctx.drawImage( @image.image, sx, sy, @w, @h, @rX - (@w - @world.tileWidth), @rY - (@h - @world.tileHeight), @w * @world.scale, @h*@world.scale )
      
      
  
  kill: (modifier) =>
    that = this
    @world.sprites[t..t] = [] if ( t = @world.sprites.indexOf(that))
    

  reset: ->
    @nextStep=[]
    @vx = 0
    @vy = 0
    @path = [[],[]] 
    @x = @defaultX
    @y = @defaultY
    
      
  twoDToIso: (ex, wy, w, h)->
    tileX = Math.floor ( (@rX + @world.scrollX)  / @world.tileWidth ) + ( (@rY + @world.scrollY)  / @world.tileHeight)  
    tileY = Math.floor ( (@rY + @world.scrollY) / @world.tileHeight ) - ( (@rX + @world.scrollX) / @world.tileWidth) 
    {x: tileX, y:tileY}
    
  
  getTile:(x = @rX, y=@rY) =>
    if @world.iso
      matrix = @twoDToIso x, y, @world.tileWidth, @world.tileHeight 
    else
      px = Math.floor @rX / @world.tileWidth
      py = Math.floor @rY / @world.tileHeight 
      matrix = {x: Math.floor(@x / @world.tileWidth), y: Math.floor (@y / @world.tileHeight)}
    matrix
    
  walkPath: (path) ->
    @path = path
    if @path[1]
      @nextStep = @path[1] 
      @nextX = @world.background.mapTiles[@nextStep[1]][@nextStep[0]].x
      @nextY = @world.background.mapTiles[@nextStep[1]][@nextStep[0]].y
      
      deltaX = @nextX - @x
      deltaY = @nextY - @y
      
      #clear path as you go
      @world.background.mapTiles[@path[0][1]][@path[0][0]].clearFlags 'path'
      
      if deltaX != 0
        if deltaX > 0
          #move right
          @vx = @speedX
        if deltaX < 0
          #move left
          @vx = -@speedX
       
      if deltaY != 0
        if deltaY > 0
          #move down
          @vy = @speedY
        if deltaY < 0
          #move up
          @vy = -@speedY
      
    else
      false


###
~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~
~The Player Class
~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~
###

class Player extends Entity
  name: 'Player'
  
  
  constructor: ->
    super()
    @speedX = 3
    @speedY = 3
    if @world.iso
      @speedX *= 2
    @entType = 'player'
    @animations = {}
    @animations.standing = [0]
    @animations.walkDownLeft = [1,1,1,2,2,2,3,3,3,4,4,4,5,5,5,6,6,6]
    @animations.walkDownRight = [7,7,7,8,8,8,9,9,9,10,10,10,11,11,11]
  
  update:(modifier) ->
    if @vx < 0 and @vy > 0
      @animate(@frame + 1, @animations.walkDownLeft)
      
    if @vx > 0 and @vy > 0
      @animate(@frame + 1, @animations.walkDownRight)
    
    if @vx is 0 and @vy is 0
      @animate( 0, @animations.standing)
     
          
    super()
    
  draw: ->
    super() 
    if @world.debug
      @world.ctx.strokeStyle = 'black'
      @world.ctx.strokeRect @rX , @rY , @w, @h
    
  setActive: ->
    @world.player = this
    @world.quickScroll = true
    
class DrawnPlayer extends Player
  constructor: ->
    super()
    @colourTop = '#c4ffeb'
    @colourRight = '#9be1c9'
    @colourLeft = '#80b9a6'
    
  draw: =>  
     that = this
     @world.ctx.fillStyle = @colourLeft
     @world.ctx.beginPath()
     @world.ctx.moveTo @rX, @rY + @world.tileHeight / 2
     @world.ctx.lineTo @rX, @rY - @world.tileHeight / 2
     @world.ctx.lineTo @rX + (@world.tileWidth / 2), @rY - (@world.tileHeight)
     @world.ctx.lineTo @rX + (@world.tileWidth / 2), @rY + @world.tileHeight
     @world.ctx.closePath()
     @world.ctx.fill()
     
     
     @world.ctx.fillStyle = @colourRight
     @world.ctx.beginPath()
     @world.ctx.moveTo @rX + @w, @rY + @world.tileHeight / 2
     @world.ctx.lineTo @rX + @w, @rY - @world.tileHeight / 2
     @world.ctx.lineTo @rX + (@world.tileWidth / 2), @rY - (@world.tileHeight)
     @world.ctx.lineTo @rX + (@world.tileWidth / 2), @rY + @world.tileHeight
     @world.ctx.closePath()
     @world.ctx.fill()
     
     @world.ctx.fillStyle = @colourTop
     @world.ctx.beginPath()
     @world.ctx.moveTo @rX + @w, @rY - @world.tileHeight / 2
     @world.ctx.lineTo @rX + (@world.tileWidth / 2), @rY - (@world.tileHeight)
     @world.ctx.lineTo @rX, @rY - @world.tileHeight / 2
     @world.ctx.lineTo @rX + (@world.tileWidth / 2), @rY
     @world.ctx.closePath()
     @world.ctx.fill()
     
     if @world.player == that
       @world.ctx.strokeStyle = 'yellow'
       @world.ctx.beginPath()
       @world.ctx.moveTo @rX, @rY + (@h / 2)
       @world.ctx.lineTo @rX + (@w / 2), @rY + @h
       @world.ctx.lineTo @rX + @w, @rY + (@h / 2)
       @world.lineWidth = 2
       @world.ctx.stroke()
     
     if @world.debug
        @strokeStyle = 'black'
        @world.ctx.strokeRect(@rX, @rY, @w, @h)
        @strokeStyle = 'blue'
        @world.ctx.strokeRect @rX, @rY, 4, 4
     
###
~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~
~The Control Class
~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~
###  
class Control extends Sprite
   
   collides: true
   switchedOn: true
   
   frame: 0
   
   constructor: (world, @x, @y, @w, @h, image, @linkedTo, @name = 'control') ->
     super world, image
     @world.controls.push this
     if @world.debug then console.log 'created a control linked to ' + @linkedTo.name
     
   update: (modifier) =>
     that = this
     if @world.collisionIndex[@name]
       for control in @world.controls
         if control != that
           if control.linkedTo == @linkedTo
             control.switchedOn = false if control.switchedOn
      
       @switchedOn = true
       
       collides = @world.collisionIndex[@name]
       if !@linkedTo.active
         @linkedTo.active = true
         @linkedTo.startMoving()
     else
       if @switchedOn
         @switchedOn = false
         @linkedTo.active = false
         
     @frame = if @switchedOn then 1 else 0
         
     super modifier
     
   draw: ->
     if !@image
       @world.ctx.strokeStyle = 'blue'
       @world.ctx.strokeRect @rX, @rY, @w, @h / 2
       
     else
       @rY = @rY - (5 * @world.scale)
       super()
   
     
###
~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~
~The Item Class
~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~
###  
class Item extends Sprite

  collides:true
  
  constructor: (world, @x, @y, @w, @h, image, @name='item')->
    super world, image
    
  update: (modifier) =>
     that = this
     if @world.collisionIndex[@name]
       collides = @world.collisionIndex[@name]
       if collides.entType == 'player'
         @world.inventory.push this
         @kill()
         
     super()
       
  draw: ->
    if !@image
      @world.ctx.beginPath()
      @world.ctx.arc(@rX + (@w / 2), @rY, @w / 2, 0, 2 * Math.PI, false)
      @world.ctx.fillStyle = 'rgb(234,204,112)'
      @world.ctx.fill()
    else
      super()
      
  
  kill: (modifier) =>
    that = this
    @world.sprites[t..t] = [] if ( t = @world.sprites.indexOf(that))
    
  
  
  
###
~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~
~The NPC Class
~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~
###
class NPC extends Entity
  
  name: 'Smith'
    
    
  constructor: ->
    super()
    @speedX = 1.5
    @speedY = 1.5
    @entType = 'npc'
    if @world.iso
      @speedX *= 2
        
  update: (modifier) ->
    super modifier
    if @loopPath and @path.length < 3
      @clearPath()
      @setPath @initialPath, true

  setPath: (path, @loopPath = false) ->
     @initialPath = []
     for item in path
       @initialPath.push item
     @path = path
     
  clearPath: ->
     @path = []
 
class DrawnNPC extends NPC
  constructor: ->
    super()
    @colourTop = '#dbdbdb'
    @colourRight = '#bdbdbd'
    @colourLeft = '#aeaeae'
    
    
  draw: ->  
  
     @world.ctx.fillStyle = @colourLeft
     @world.ctx.beginPath()
     @world.ctx.moveTo @rX, @rY + @world.tileHeight / 2
     @world.ctx.lineTo @rX, @rY - @world.tileHeight / 2
     @world.ctx.lineTo @rX + (@world.tileWidth / 2), @rY - (@world.tileHeight)
     @world.ctx.lineTo @rX + (@world.tileWidth / 2), @rY + @world.tileHeight
     @world.ctx.closePath()
     @world.ctx.fill()
     
     
     @world.ctx.fillStyle = @colourRight
     @world.ctx.beginPath()
     @world.ctx.moveTo @rX + @w, @rY + @world.tileHeight / 2
     @world.ctx.lineTo @rX + @w, @rY - @world.tileHeight / 2
     @world.ctx.lineTo @rX + (@world.tileWidth / 2), @rY - (@world.tileHeight)
     @world.ctx.lineTo @rX + (@world.tileWidth / 2), @rY + @world.tileHeight
     @world.ctx.closePath()
     @world.ctx.fill()
     
     @world.ctx.fillStyle = @colourTop
     @world.ctx.beginPath()
     @world.ctx.moveTo @rX + @w, @rY - @world.tileHeight / 2
     @world.ctx.lineTo @rX + (@world.tileWidth / 2), @rY - (@world.tileHeight)
     @world.ctx.lineTo @rX, @rY - @world.tileHeight / 2
     @world.ctx.lineTo @rX + (@world.tileWidth / 2), @rY
     @world.ctx.closePath()
     @world.ctx.fill()
     
     if @world.debug
      @strokeStyle = 'black'
      @world.ctx.strokeRect(@rX, @rY, @w, @h)
      @strokeStyle = 'blue'
      @world.ctx.strokeRect @rX, @rY, 4, 4
     
        


###
START THE GAME!
###

  
map = [
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1], 
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1], 
    [1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1], 
    [1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1], 
    [1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1], 
    [1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1], 
    [1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1], 
    [1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1], 
    [1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1], 
    [1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1], 
    [1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1], 
    [1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1], 
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
  ]


window.onload = ->

  game = new Game 'game', 30, scale:.5
  game.iso = true
  game.run()
  game.world.createWorld map
  game.world.scrollX = -250
  #game.world.debug = true
  
  ###
  bind mousey
  ###
  
  $('canvas').on('click', ()->
    game.inputHandler.clicked = true  
  )
	
  pX = game.world.background.mapTiles[2][17].x
  pY = game.world.background.mapTiles[2][17].y
  player = new DrawnPlayer game.world,pX, pY, 60, 30, 'images/eric.png', 10
  
  p2X = game.world.background.mapTiles[1][17].x
  p2Y = game.world.background.mapTiles[1][17].y
  player2 = new DrawnPlayer game.world,p2X, p2Y, 60, 30, 'images/eric.png', 10
  
  player.name = 'Ebrewe'
  player2.name = 'client'
  
  player2.colourTop = '#a4efeb'
  player2.colourRight = '#8bd1c9'
  player2.colourLeft = '#70a9a6'
  
  
  npcX = game.world.background.mapTiles[9][5].x
  npcY = game.world.background.mapTiles[9][5].y
  #Badguy
  badRobot = new DrawnNPC game.world, npcX, npcY, 60, 60
  npcPath = [
    [5,9],[5,10],[5,11],[5,12],
    [11,12],
    [11,5],
    [5,5],
    [5,9]
  ]
  badRobot.setPath npcPath, yes
  
  
  pfX = game.world.background.mapTiles[9][18].x
  pfY = game.world.background.mapTiles[9][18].y
  
  pfX2 = game.world.background.mapTiles[7][16].x
  pfY2 = game.world.background.mapTiles[7][16].y
  
  platform = new Platform game.world, pfX, pfY, game.world.tileWidth, game.world.tileHeight, true, [pfX, pfY], [pfX2, pfY2], [18, 9], [16, 7]
    

  prX = game.world.background.mapTiles[11][4].x
  prY = game.world.background.mapTiles[11][4].y
  
  prX2 = game.world.background.mapTiles[11][3].x
  prY2 = game.world.background.mapTiles[11][3].y
  
  platform2 = new Platform game.world, prX, prY, game.world.tileWidth, game.world.tileHeight, true, [prX, prY], [prX2, prY2], [4, 11], [3, 11]
 
  cX = game.world.background.mapTiles[1][13].x
  cY = game.world.background.mapTiles[1][13].y
  control = new Control game.world, cX, cY, 60, 35, 'http://games.ericbrewer.ca/cdn/images/buttonTileIso.png', platform
  
  c2X = game.world.background.mapTiles[11][16].x
  c2Y = game.world.background.mapTiles[11][16].y
  control2 = new Control game.world, c2X, c2Y, 60, 35, 'http://games.ericbrewer.ca/cdn/images/buttonTileIso.png', platform
  
  c3X = game.world.background.mapTiles[3][4].x
  c3Y = game.world.background.mapTiles[3][4].y
  control3 = new Control game.world, c3X, c3Y, 60, 35, 'http://games.ericbrewer.ca/cdn/images/buttonTileIso.png', platform2
  
  control.name = 'elControl'
  control2.name = 'elTwoControl'
  control3.name ='platformControl'
  
  iX = game.world.background.mapTiles[11][1].x
  iY = game.world.background.mapTiles[11][1].y
  goal = new Item game.world, iX, iY, 30, 30, false, 'goal'
  
  player.setActive()
  
  ###
  bind players
  ###
  $('.buttons').on('click', '.player', (e)->
      bId = $(this).attr('id')
      e = e ? e : window.event
      e.preventDefault()
      e.stopPropagation()
      
      $('.active').removeClass('active')
      $(this).addClass('active')
      
      
      switch bId
        when 'player1' then player.setActive()
        when 'player2' then player2.setActive()
        else player.setActive()
    )
              
            
!
999px

Console