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!
View Compiled
.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%);
}
}
}
View Compiled
###
~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~
~ 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()
)
View Compiled
This Pen doesn't use any external CSS resources.