Compare commits
No commits in common. "gh-pages" and "master" have entirely different histories.
4
.gitignore
vendored
|
@ -1 +1,3 @@
|
|||
node_modules
|
||||
node_modules
|
||||
public/app.js
|
||||
.Thumbs.db
|
||||
|
|
3
README.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
1. Install dependencies with `npm install --global`.
|
||||
2. Run the browser watch with `gulp`.
|
||||
3. hack hack hack, until the time is over.
|
954
app.js
BIN
assets/Musik/Ingame/Ingame_02.ogg
Normal file
BIN
assets/Musik/Ingame/Ingame_03.ogg
Normal file
BIN
assets/Musik/Ingame/Ingame_04.ogg
Normal file
BIN
assets/Musik/Ingame/Robert del Naja - SK.mp3
Normal file
BIN
assets/Sounds/EchoSonar.mp3
Normal file
BIN
assets/Sounds/Menue/Aktivieren.mp3
Normal file
BIN
assets/Sounds/Menue/Auswaehlen.mp3
Normal file
BIN
assets/Sounds/Menue/Zurueck.mp3
Normal file
BIN
assets/Sounds/Motherbase.mp3
Normal file
BIN
assets/Sounds/Silo.mp3
Normal file
BIN
assets/Sounds/Solarpanel.mp3
Normal file
BIN
assets/Sounds/Sonde.mp3
Normal file
BIN
assets/Sounds/Upgrade_complete.mp3
Normal file
BIN
assets/Terrain/Test 16x16.png
Normal file
After Width: | Height: | Size: 891 B |
BIN
assets/Terrain/Test 8X8.png
Normal file
After Width: | Height: | Size: 755 B |
BIN
assets/Terrain/Thumbs.db
Normal file
BIN
assets/Terrain/layers-tileset.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
assets/cube/Thumbs.db
Normal file
BIN
assets/cube/cuberotate-0000.jpg
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
assets/cube/cuberotate-0001.jpg
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
assets/cube/cuberotate-0002.jpg
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
assets/cube/cuberotate-0003.jpg
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
assets/cube/cuberotate-0004.jpg
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
assets/cube/cuberotate-0005.jpg
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
assets/cube/cuberotate-0006.jpg
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
assets/cube/cuberotate-0007.jpg
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
assets/cube/cuberotate-0008.jpg
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
assets/cube/cuberotate-0009.jpg
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
assets/tileset/Thumbs.db
Normal file
BIN
assets/videos/TinyTake07-12-2014-09-07-47.mp4
Normal file
35
gulpfile.js
Normal file
|
@ -0,0 +1,35 @@
|
|||
// npm install -g gulp
|
||||
// npm install --save-dev browser-sync
|
||||
|
||||
var gulp = require('gulp');
|
||||
|
||||
var coffee = require('gulp-coffee');
|
||||
var concat = require('gulp-concat');
|
||||
var uglify = require('gulp-uglify');
|
||||
var sourcemaps = require('gulp-sourcemaps');
|
||||
|
||||
var browserSync = require('browser-sync');
|
||||
var reload = browserSync.reload;
|
||||
|
||||
|
||||
gulp.task('server', function() {
|
||||
browserSync({
|
||||
server: {
|
||||
baseDir: 'public'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
gulp.task('compile', function() {
|
||||
return gulp.src(['src/entities/*.coffee', 'src/items/*.coffee', , 'src/tiles/*.coffee', 'src/tools.coffee', 'src/app.coffee', 'src/game.coffee', 'src/hud.coffee', 'src/speechbubble.coffee'])
|
||||
.pipe(sourcemaps.init())
|
||||
.pipe(coffee({bare: true}))
|
||||
.pipe(concat('app.js'))
|
||||
.pipe(sourcemaps.write())
|
||||
.pipe(gulp.dest('public'));
|
||||
});
|
||||
|
||||
gulp.task('default', ['server'], function() {
|
||||
gulp.watch(['src/**/*.coffee'], ['compile']);
|
||||
gulp.watch(['*.html', 'styles.css', 'app.js', 'images/*'], {cwd: 'public'}, reload);
|
||||
});
|
7
notes.org
Normal file
|
@ -0,0 +1,7 @@
|
|||
Title: Entire game on one screen
|
||||
|
||||
* TODO
|
||||
** make video with audio comment :ruben:
|
||||
** submit to ludum dare :ruben:
|
||||
** write ludum dare final blogpost :ruben:
|
||||
** write post-mortem ludum dare blogpost :aaron:ruben:
|
13
package.json
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"name": "arg-games-ld31",
|
||||
"description": "ARG-Games Lumdum Date 31 Entry",
|
||||
"version": "0.0.1",
|
||||
"dependencies": {
|
||||
"gulp": "*",
|
||||
"gulp-coffee": "*",
|
||||
"gulp-concat": "*",
|
||||
"gulp-uglify": "*",
|
||||
"gulp-sourcemaps": "*",
|
||||
"browser-sync": "*"
|
||||
}
|
||||
}
|
954
public/app.js
Before Width: | Height: | Size: 662 B After Width: | Height: | Size: 662 B |
Before Width: | Height: | Size: 187 B After Width: | Height: | Size: 187 B |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 953 B After Width: | Height: | Size: 953 B |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 915 B After Width: | Height: | Size: 915 B |
Before Width: | Height: | Size: 2 KiB After Width: | Height: | Size: 2 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 1 KiB |
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 6 KiB After Width: | Height: | Size: 6 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 136 B After Width: | Height: | Size: 136 B |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 9.4 KiB |
BIN
release/spacediggers-1.0.zip
Normal file
22
src/app.coffee
Normal file
|
@ -0,0 +1,22 @@
|
|||
app = playground(
|
||||
width: 8*20,
|
||||
height: 8*15,
|
||||
scaleToFit: true,
|
||||
smoothing: false,
|
||||
|
||||
create: ->
|
||||
@loadImages "layers", "active", "progress", "selected", "entities", "hud", "actions", "speechbubbles", "deadtiles", "layerdetails", "entitydetails", "buildinfo", "cursor", "info", "end", "intro1", "intro2", "intro3", "intro4", "titlescreen"
|
||||
@currentHoveredTile = new Tile
|
||||
|
||||
ready: ->
|
||||
@game.start()
|
||||
@setState @game
|
||||
|
||||
render: ->
|
||||
@layer.clear "#00f"
|
||||
@game.render()
|
||||
|
||||
layerIndexToName: (index)->
|
||||
resTypes = (k for own k of @game.resources)
|
||||
resTypes[index]
|
||||
)
|
26
src/entities/base.coffee
Normal file
|
@ -0,0 +1,26 @@
|
|||
class Base
|
||||
constructor: ->
|
||||
@frame = 0
|
||||
|
||||
window.setInterval @changeAnimation, 500
|
||||
|
||||
tick: (tile)->
|
||||
|
||||
sprite: ->
|
||||
[@frame*8, 0, 8, 8]
|
||||
|
||||
spritedetail: ->
|
||||
[0, 0, 16, 16]
|
||||
|
||||
isMoveable: ->
|
||||
false
|
||||
|
||||
changeAnimation: =>
|
||||
if @frame == 3
|
||||
@frame = 0
|
||||
else
|
||||
@frame += 1
|
||||
|
||||
spaceProvided: 30
|
||||
energyProvided: 7
|
||||
isDockable: true
|
29
src/entities/miner.coffee
Normal file
|
@ -0,0 +1,29 @@
|
|||
class Miner
|
||||
constructor: ->
|
||||
@frame = 0
|
||||
window.setInterval @changeAnimation, 500
|
||||
|
||||
tick: (tile) ->
|
||||
tile.click "left"
|
||||
tile.click "left"
|
||||
tile.click "left"
|
||||
tile.click "left"
|
||||
|
||||
sprite: ->
|
||||
[@frame*8, 16, 8, 8]
|
||||
|
||||
spritedetail: ->
|
||||
[0, 16*2, 16, 16]
|
||||
|
||||
isMoveable: ->
|
||||
true
|
||||
|
||||
changeAnimation: =>
|
||||
if @frame == 1
|
||||
@frame = 0
|
||||
else
|
||||
@frame += 1
|
||||
|
||||
spaceProvided: 5
|
||||
energyProvided: 0
|
||||
isDockable: false
|
27
src/entities/silo.coffee
Normal file
|
@ -0,0 +1,27 @@
|
|||
class Silo
|
||||
constructor: ->
|
||||
@frame = 0
|
||||
window.setInterval @changeAnimation, 500
|
||||
|
||||
tick: (tile)->
|
||||
|
||||
sprite: ->
|
||||
[@frame*8, 8, 8, 8]
|
||||
|
||||
spritedetail: ->
|
||||
[0, 16, 16, 16]
|
||||
|
||||
isMoveable: ->
|
||||
false
|
||||
|
||||
changeAnimation: =>
|
||||
if @frame == 1
|
||||
@frame = 0
|
||||
else
|
||||
@frame += 1
|
||||
|
||||
spaceProvided: 15
|
||||
energyProvided: 0
|
||||
|
||||
isDockable: true
|
||||
|
15
src/entities/solarpanel.coffee
Normal file
|
@ -0,0 +1,15 @@
|
|||
class Solarpanel
|
||||
tick: (tile)->
|
||||
|
||||
sprite: ->
|
||||
[0, 8*3, 8, 8]
|
||||
|
||||
spritedetail: ->
|
||||
[0, 16*3, 16, 16]
|
||||
|
||||
isMoveable: ->
|
||||
false
|
||||
|
||||
spaceProvided: 0
|
||||
energyProvided: 15
|
||||
isDockable: true
|
264
src/game.coffee
Normal file
|
@ -0,0 +1,264 @@
|
|||
app.game =
|
||||
start: ->
|
||||
for i in [0..20*15-1]
|
||||
@map[i] = new Tile(i)
|
||||
@map[20*5+10].entity = new Base
|
||||
|
||||
@mouseX = 0
|
||||
@mouseY = 0
|
||||
@currentHoveredTile = new Tile(-1)
|
||||
@currentSelectedTile = null
|
||||
|
||||
window.setInterval @tick, 1000
|
||||
@hud.start()
|
||||
@speechbubble.start()
|
||||
|
||||
@cutScene = false
|
||||
@intro = false
|
||||
@titleScreen = true
|
||||
|
||||
# TODO: Refactor this whole crap ... I can't belive I am writing this ...
|
||||
startCutScene: ->
|
||||
if @titleScreen
|
||||
@titleScreen = false
|
||||
@cutScene = true
|
||||
app.game.cutSceneImage = app.images.intro1
|
||||
window.setTimeout app.game.cutScene2, 1500
|
||||
|
||||
cutScene2: =>
|
||||
app.game.cutSceneImage = app.images.intro2
|
||||
window.setTimeout app.game.cutScene3, 2000
|
||||
|
||||
cutScene3: =>
|
||||
app.game.cutSceneImage = app.images.intro3
|
||||
window.setTimeout app.game.cutScene4, 1500
|
||||
|
||||
cutScene4: =>
|
||||
app.game.cutSceneImage = app.images.intro4
|
||||
window.setTimeout app.game.cutSceneEnd, 1500
|
||||
|
||||
cutSceneEnd: =>
|
||||
app.game.cutScene = false
|
||||
app.game.intro = true
|
||||
app.game.startIntro()
|
||||
|
||||
startIntro: ->
|
||||
@speechbubble.setFix 90, 27
|
||||
@speechbubble.say 'help', 2000
|
||||
|
||||
@timeout = window.setTimeout @intro2, 3000
|
||||
|
||||
intro2: =>
|
||||
app.game.speechbubble.say 'damn', 2000
|
||||
app.game.timeout = window.setTimeout app.game.intro3, 3000
|
||||
|
||||
intro3: =>
|
||||
app.game.speechbubble.say 'need', 3500
|
||||
app.game.timeout = window.setTimeout app.game.intro4, 4500
|
||||
|
||||
intro4: =>
|
||||
app.game.speechbubble.say 'collect', 3500
|
||||
app.game.timeout = window.setTimeout app.game.introEnd, 3500
|
||||
|
||||
introEnd: =>
|
||||
@intro = false
|
||||
app.game.speechbubble.setMouse()
|
||||
|
||||
render: ->
|
||||
if @titleScreen
|
||||
app.layer.drawImage app.images.titlescreen, 0, 0, 20*8, 15*8
|
||||
return
|
||||
|
||||
if @cutScene
|
||||
app.layer.drawImage @cutSceneImage, 0, 0, 20*8, 15*8
|
||||
return
|
||||
|
||||
if @gameEndCheck()
|
||||
app.layer.drawImage app.images.end, 0, 0, 20*8, 15*8
|
||||
return
|
||||
|
||||
for tile, i in @map
|
||||
y = Math.floor(i/20)
|
||||
x = i-(y*20)
|
||||
tile.render(x, y)
|
||||
@hud.render()
|
||||
@speechbubble.render()
|
||||
|
||||
mousedown: (event)->
|
||||
tile = posToTile(Math.floor(event.x/8), Math.floor(event.y/8))
|
||||
|
||||
# Can't click on dead tiles
|
||||
return unless tile and tile.isBuildable
|
||||
|
||||
if @isMouseInView event.x/8, event.y/8
|
||||
switch event.button
|
||||
when 'left'
|
||||
if event.x > 143 and event.x < 151 and event.y > 95 and event.y < 106
|
||||
app.game.hud.showBuildInfo()
|
||||
else
|
||||
tile.click(event.button)
|
||||
|
||||
@currentSelectedTile.deselect() if @currentSelectedTile
|
||||
tile.select()
|
||||
@currentSelectedTile = tile
|
||||
when 'right'
|
||||
@currentSelectedTile.deselect() if @currentSelectedTile
|
||||
@currentSelectedTile = null
|
||||
|
||||
mousemove: (event)->
|
||||
@mouseX = event.x
|
||||
@mouseY = event.y
|
||||
|
||||
if @isMouseInView event.x, event.y
|
||||
tile = posToTile(Math.floor(event.x/8), Math.floor(event.y/8))
|
||||
|
||||
if tile
|
||||
if tile != @currentHoveredTile
|
||||
tile.moveIn()
|
||||
@currentHoveredTile.moveOut() if @currentHoveredTile
|
||||
@currentHoveredTile = tile
|
||||
else
|
||||
@currentHoveredTile.moveOut() if @currentHoveredTile
|
||||
@currentHoveredTile = null
|
||||
|
||||
isMouseInView: (mouseX, mouseY) ->
|
||||
if mouseX < app.width and mouseX >= 0 and mouseY < app.height and mouseY >= 0
|
||||
return true
|
||||
|
||||
false
|
||||
|
||||
keyup: (event) ->
|
||||
switch event.key
|
||||
when "enter" then @startCutScene()
|
||||
when "m" then @createMiner()
|
||||
when "e" then @createSolarpanel()
|
||||
when "i" then app.game.hud.showBuildInfo()
|
||||
when "s" then @createSilo()
|
||||
when "c" then @cheatah()
|
||||
when "1" then @releaseRes 'stardust'
|
||||
when "2" then @releaseRes 'dirt'
|
||||
when "3" then @releaseRes 'bedrock'
|
||||
when "4" then @releaseRes 'oxodum'
|
||||
when "5" then @releaseRes 'lubinit'
|
||||
when "6" then @releaseRes 'darkana'
|
||||
when "7" then @releaseRes 'bio'
|
||||
when "8" then @releaseRes 'notch'
|
||||
when "9" then @releaseRes 'lava'
|
||||
when "space"
|
||||
@currentSelectedTile.deselect() if @currentSelectedTile
|
||||
@currentSelectedTile = null
|
||||
|
||||
releaseRes: (string) ->
|
||||
@resources[string] = 0
|
||||
|
||||
tick: =>
|
||||
tile.tick() for tile in app.game.map
|
||||
|
||||
createMiner: ->
|
||||
if @currentSelectedTile and !@currentSelectedTile.entity
|
||||
if @checkResource('lubinit', 5, true)
|
||||
@currentSelectedTile.entity = new Miner
|
||||
else
|
||||
@speechbubble.say 'nores'
|
||||
else
|
||||
@speechbubble.say 'nosel'
|
||||
|
||||
createSilo: ->
|
||||
if @currentSelectedTile
|
||||
if @checkPosition(@currentSelectedTile)
|
||||
if @checkResource('dirt', 5, true)
|
||||
@currentSelectedTile.entity = new Silo
|
||||
else
|
||||
@speechbubble.say 'nores'
|
||||
else
|
||||
@speechbubble.say 'toofar'
|
||||
else
|
||||
@speechbubble.say 'nosel'
|
||||
|
||||
# TODO: OMG refactor this ...
|
||||
createSolarpanel: ->
|
||||
if @currentSelectedTile
|
||||
if @checkPosition(@currentSelectedTile)
|
||||
if @checkResource('notch', 30, true)
|
||||
@currentSelectedTile.entity = new Solarpanel
|
||||
else
|
||||
@speechbubble.say 'nores'
|
||||
else
|
||||
@speechbubble.say 'toofar'
|
||||
else
|
||||
@speechbubble.say 'nosel'
|
||||
|
||||
checkResource: (type, amount, drain = false) ->
|
||||
if @resources[type] >= amount
|
||||
@resources[type] -= amount if drain
|
||||
return true
|
||||
false
|
||||
|
||||
checkPosition: (tile)->
|
||||
return false if tile.entity
|
||||
|
||||
# Check all 4 directions
|
||||
[x, y] = posToXY(tile.position)
|
||||
|
||||
# Left
|
||||
return true if app.game.map[xyToPos(x-1, y)].entity \
|
||||
and app.game.map[xyToPos(x-1, y)].entity.isDockable \
|
||||
and x > 0
|
||||
|
||||
# Right
|
||||
return true if app.game.map[xyToPos(x+1, y)].entity \
|
||||
and app.game.map[xyToPos(x+1, y)].entity.isDockable \
|
||||
and x < 19
|
||||
|
||||
# Top
|
||||
return true if app.game.map[xyToPos(x, y-1)].entity \
|
||||
and app.game.map[xyToPos(x, y-1)].entity.isDockable \
|
||||
and y > 0
|
||||
|
||||
# Bottom
|
||||
return true if app.game.map[xyToPos(x, y+1)].entity \
|
||||
and app.game.map[xyToPos(x, y+1)].entity.isDockable \
|
||||
and y < 14
|
||||
|
||||
false
|
||||
|
||||
cheatah: ->
|
||||
for type, amount of @resources
|
||||
@resources[type] = 100
|
||||
|
||||
map: []
|
||||
miners: []
|
||||
maxTileAmount: 75
|
||||
|
||||
availableSiloStorage: ->
|
||||
space = 0
|
||||
for tile in app.game.map
|
||||
space += tile.entity.spaceProvided if tile.entity
|
||||
space
|
||||
|
||||
usedSiloStorage: ->
|
||||
space = 0
|
||||
space += amount for resource, amount of @resources
|
||||
space
|
||||
|
||||
solarpanelCount: ->
|
||||
energy = 0
|
||||
for tile in app.game.map
|
||||
# FIXME: Thats not a sane solution hahahah :D
|
||||
energy += 1 if tile.entity and tile.entity.energyProvided > 10
|
||||
energy
|
||||
|
||||
gameEndCheck: ->
|
||||
return true if @solarpanelCount() >= 4
|
||||
false
|
||||
|
||||
resources:
|
||||
stardust: 0
|
||||
dirt: 0
|
||||
bedrock: 0
|
||||
oxodum: 0
|
||||
lubinit: 0
|
||||
darkana: 0
|
||||
bio: 0
|
||||
notch: 0
|
||||
lava: 0
|
125
src/hud.coffee
Normal file
|
@ -0,0 +1,125 @@
|
|||
app.game.hud =
|
||||
start: ->
|
||||
resTypes = (k for own k of app.game.resources)
|
||||
|
||||
@position = x: 45, y: 103
|
||||
@buildinfo = false
|
||||
|
||||
@itemArrow = new AnimatedItem maxFrames: 10, image: app.images.actions, speed: 50
|
||||
|
||||
@resources = []
|
||||
for restype, i in resTypes
|
||||
@resources[restype] = new Tilelayer(
|
||||
type: restype,
|
||||
depth: i
|
||||
)
|
||||
|
||||
render: ->
|
||||
panelusage = 'resources'
|
||||
app.layer.drawImage app.images.hud, 0, 11*8
|
||||
|
||||
app.layer.drawImage app.images.info, 143, 95
|
||||
|
||||
# cursor
|
||||
# app.layer.drawImage app.images.cursor, app.game.mouseX, app.game.mouseY
|
||||
|
||||
if @buildinfo
|
||||
app.layer.drawRegion app.images.buildinfo, [0, 0, 106, 10], 1, 1
|
||||
app.layer.drawRegion app.images.buildinfo, [0, 10, 106, 10], 1, 12
|
||||
app.layer.drawRegion app.images.buildinfo, [0, 20, 106, 10], 1, 23
|
||||
app.layer.drawRegion app.images.buildinfo, [0, 30, 106, 10], 1, 34
|
||||
|
||||
currentSelectedTile = app.game.currentSelectedTile
|
||||
if currentSelectedTile != null
|
||||
panelusage = 'tile'
|
||||
|
||||
if currentSelectedTile.entity
|
||||
panelusage = 'entity'
|
||||
app.layer.drawRegion app.images.entitydetails, currentSelectedTile.entity.spritedetail(), 12, 95
|
||||
else
|
||||
app.layer.drawRegion app.images.layerdetails, currentSelectedTile.getCurrentLayer().spritedetail, 12, 95
|
||||
|
||||
# silo capacity
|
||||
usedSiloStoragePercent = Math.round((100 / app.game.availableSiloStorage()) * app.game.usedSiloStorage())
|
||||
for f in [0..100]
|
||||
resourcePanelColor = "#333"
|
||||
|
||||
if f <= usedSiloStoragePercent
|
||||
colorStep = Math.round((usedSiloStoragePercent/100)*5)
|
||||
resourcePanelColor = ["#0a0", "#0a0", "#aa0", "#f60", "#a00", "#f00"][colorStep]
|
||||
|
||||
x = 44+f
|
||||
y = 112
|
||||
app.layer.setPixel(resourcePanelColor, x, y)
|
||||
|
||||
# Energy production (47)
|
||||
|
||||
length = Math.round(((25*app.game.solarpanelCount())*45)/100)
|
||||
for i in [0..length]
|
||||
app.layer.setPixel("#228ca5", 49+i, 91)
|
||||
app.layer.setPixel("#8ddaed", 50+i, 92)
|
||||
app.layer.setPixel("#228ca5", 49+i, 93)
|
||||
|
||||
switch panelusage
|
||||
when 'tile'
|
||||
@showResources()
|
||||
when 'entity'
|
||||
#app.layer.drawRegion app.images.entities, currentSelectedTile.entity.sprite(), 44, 102
|
||||
if currentSelectedTile.entity.isMoveable()
|
||||
app.layer.drawRegion @itemArrow.image, @itemArrow.sprite(), 44, 102
|
||||
when 'resources'
|
||||
@showResources()
|
||||
|
||||
showBuildInfo: ->
|
||||
clearTimeout(@timeout) if @timeout
|
||||
@buildinfo = true
|
||||
@timeout = window.setTimeout @hideBuildInfo, 6000
|
||||
|
||||
hideBuildInfo: ->
|
||||
app.game.hud.buildinfo = false
|
||||
|
||||
showResources: ->
|
||||
# resources
|
||||
i = 0
|
||||
for type, amount of app.game.resources
|
||||
if amount > 0
|
||||
tileLayer = @resources[type]
|
||||
|
||||
spritePosition = {
|
||||
x: i*9+@position.x
|
||||
y: @position.y
|
||||
}
|
||||
|
||||
app.layer.drawRegion app.images.layers, tileLayer.hudSprite, spritePosition.x, spritePosition.y
|
||||
|
||||
amountByTwenty = Math.floor(amount/20)
|
||||
amountLeft = amount - amountByTwenty*20
|
||||
for e in [0..amountLeft]
|
||||
color = "#0a0"
|
||||
color = "#0f0" if e == amountLeft
|
||||
|
||||
if e < 6
|
||||
x = spritePosition.x-1+e
|
||||
y = spritePosition.y-1
|
||||
else if e < 10
|
||||
x = spritePosition.x+4
|
||||
y = spritePosition.y-1+e-5
|
||||
else if e < 15
|
||||
x = spritePosition.x+14-e
|
||||
y = spritePosition.y+4
|
||||
else
|
||||
x = spritePosition.x-1
|
||||
y = spritePosition.y+19-e
|
||||
|
||||
app.layer.setPixel(color, x, y)
|
||||
|
||||
for f in [0..amountByTwenty]
|
||||
if f > 0
|
||||
color = "#0000ff"
|
||||
|
||||
x = spritePosition.x-2+f
|
||||
y = spritePosition.y+7
|
||||
|
||||
app.layer.setPixel(color, x, y)
|
||||
|
||||
i++
|
15
src/items/animateditem.coffee
Normal file
|
@ -0,0 +1,15 @@
|
|||
class AnimatedItem
|
||||
constructor: (options) ->
|
||||
{@maxFrames, @image, @speed} = options
|
||||
|
||||
@frame = 0
|
||||
window.setInterval @changeAnimation, @speed
|
||||
|
||||
sprite: ->
|
||||
[@frame*8, 0, 8, 8]
|
||||
|
||||
changeAnimation: =>
|
||||
if @frame == @maxFrames
|
||||
@frame = 0
|
||||
else
|
||||
@frame += 1
|
42
src/speechbubble.coffee
Normal file
|
@ -0,0 +1,42 @@
|
|||
app.game.speechbubble =
|
||||
start: ->
|
||||
@sprite = [0, 0, 27, 13]
|
||||
@positioning = 'mouse'
|
||||
|
||||
setFix: (x, y) ->
|
||||
@x = x
|
||||
@y = y
|
||||
|
||||
@positioning = 'fixed'
|
||||
|
||||
setMouse: ->
|
||||
@positioning = 'mouse'
|
||||
|
||||
say: (text, timeout = 1000) ->
|
||||
clearTimeout(@timeout) if @timeout
|
||||
|
||||
switch text
|
||||
when 'help' then @sprite = [0, 0, 27, 13]
|
||||
when 'toofar' then @sprite = [0, 13, 90, 13]
|
||||
when 'nores' then @sprite = [0, 26, 90, 13]
|
||||
when 'nosel' then @sprite = [0, 39, 90, 13]
|
||||
when 'damn' then @sprite = [0, 52, 90, 13]
|
||||
when 'need' then @sprite = [0, 65, 90, 13]
|
||||
when 'collect' then @sprite = [0, 78, 90, 13]
|
||||
|
||||
@visible = true
|
||||
@timeout = window.setTimeout @hide, timeout
|
||||
|
||||
hide: =>
|
||||
app.game.speechbubble.visible = false
|
||||
|
||||
render: ->
|
||||
switch @positioning
|
||||
when 'mouse'
|
||||
x = app.game.mouseX+5
|
||||
y = app.game.mouseY-15
|
||||
when 'fixed'
|
||||
x = @x
|
||||
y = @y
|
||||
|
||||
app.layer.drawRegion app.images.speechbubbles, @sprite, x, y if @visible
|
81
src/tiles/tile.coffee
Normal file
|
@ -0,0 +1,81 @@
|
|||
class Tile
|
||||
constructor: (position)->
|
||||
@position = position
|
||||
@layers = []
|
||||
for restype, i in allResourceTypes()
|
||||
@layers.push new Tilelayer(
|
||||
type: restype,
|
||||
depth: i,
|
||||
amount: Math.round(Math.random()*app.game.maxTileAmount)+1
|
||||
)
|
||||
|
||||
@currentLayer = 0
|
||||
@empty = false
|
||||
@entity = null
|
||||
@isActive = false
|
||||
@isBuildable = !(Math.round(Math.random()*10) == 5)
|
||||
@isBuildable = true if @position == 20*5+10
|
||||
@randomSeed = Math.round(Math.random()*10)
|
||||
|
||||
click: (button)->
|
||||
# Some tiles are not buildable
|
||||
return unless @isBuildable
|
||||
|
||||
if button == "left" and !@empty
|
||||
if (app.game.availableSiloStorage() - app.game.usedSiloStorage()) > 0
|
||||
if @layers[@currentLayer].collect()
|
||||
name = app.layerIndexToName(@currentLayer)
|
||||
app.game.resources[name] += 1
|
||||
else
|
||||
@currentLayer += 1
|
||||
|
||||
if @currentLayer == allResourceTypes().length-1
|
||||
# If we reach the bottom, the entity on top dies.
|
||||
@entity = null
|
||||
@empty = true
|
||||
|
||||
tick: ->
|
||||
@entity.tick @ if @entity
|
||||
|
||||
moveIn: ->
|
||||
@isActive = true
|
||||
|
||||
moveOut: ->
|
||||
@isActive = false
|
||||
|
||||
select: ->
|
||||
@isSelected = true
|
||||
|
||||
deselect: ->
|
||||
@isSelected = false
|
||||
|
||||
getCurrentLayer: ->
|
||||
@layers[@currentLayer]
|
||||
|
||||
render: (x, y)->
|
||||
tileLayer = @getCurrentLayer()
|
||||
app.layer.drawRegion app.images.layers, tileLayer.sprite, x*8, y*8
|
||||
|
||||
unless @isBuildable
|
||||
app.layer.drawRegion app.images.deadtiles, [8*@randomSeed, 0, 8, 8], x*8, y*8
|
||||
return
|
||||
|
||||
if @entity
|
||||
app.layer.drawRegion app.images.entities, @entity.sprite(), x*8, y*8
|
||||
|
||||
if (@entity and @entity.isMoveable()) or @isActive
|
||||
# Draw the status indicator.
|
||||
app.layer.drawImage app.images.progress, x*8, y*8
|
||||
numPercent = Math.floor((tileLayer.amount*6)/app.game.maxTileAmount)
|
||||
for i in [0..numPercent]
|
||||
color = ["#f00", "#a00", "#f60", "#aa0", "#0a0", "#0a0"][numPercent]
|
||||
color = ["#f00", "#f00", "#f80", "#ff0", "#0f0", "#0f0"][numPercent] if i == numPercent
|
||||
app.layer.setPixel(color, x*8+1+i, y*8+6)
|
||||
|
||||
if @isActive
|
||||
app.layer.drawImage app.images.active, x*8, y*8
|
||||
|
||||
if @isSelected
|
||||
app.layer.drawImage app.images.selected, x*8, y*8
|
||||
|
||||
|
11
src/tiles/tilelayer.coffee
Normal file
|
@ -0,0 +1,11 @@
|
|||
class Tilelayer
|
||||
constructor: (options)->
|
||||
{@type, @depth, @amount} = options
|
||||
@randomFactor = getRandomInt 0, 4
|
||||
@sprite = [@randomFactor*8, @depth*8, 8, 8]
|
||||
@spritedetail = [0, @depth*16, 16, 16]
|
||||
@hudSprite = [@randomFactor*8, @depth*8, 4, 4]
|
||||
|
||||
collect: ->
|
||||
return false if @amount == 0
|
||||
@amount -= 1
|
16
src/tools.coffee
Normal file
|
@ -0,0 +1,16 @@
|
|||
getRandomInt = (min, max) ->
|
||||
Math.floor(Math.random() * (max - min + 1)) + min;
|
||||
|
||||
allResourceTypes = ->
|
||||
(k for own k of app.game.resources)
|
||||
|
||||
posToTile = (x, y)->
|
||||
app.game.map[xyToPos(x, y)]
|
||||
|
||||
posToXY = (pos)->
|
||||
y = Math.floor(pos/20)
|
||||
x = pos-(y*20)
|
||||
[x, y]
|
||||
|
||||
xyToPos = (x, y)->
|
||||
y*20 + x
|