nice trees and actual player interaction
|
@ -23,7 +23,7 @@ Textures all from [OpenGameArt](https://opengameart.org/). More specifically:
|
||||||
|
|
||||||
* https://opengameart.org/content/nature-tileset
|
* https://opengameart.org/content/nature-tileset
|
||||||
* https://opengameart.org/content/platform-tileset-nature
|
* https://opengameart.org/content/platform-tileset-nature
|
||||||
* https://opengameart.org/sites/default/files/tileset2.png
|
|
||||||
* https://opengameart.org/content/cave-tileset-2
|
* https://opengameart.org/content/cave-tileset-2
|
||||||
|
* https://opengameart.org/content/monsterboy-in-wonder-world-mockup-assets
|
||||||
|
|
||||||
and partially adapted to my needs.
|
and partially adapted to my needs.
|
||||||
|
|
BIN
dist/bedrock.png
vendored
Normal file
After Width: | Height: | Size: 1.2 KiB |
4
dist/build.js
vendored
2
dist/build.js.map
vendored
BIN
dist/dwarf_left.png
vendored
Normal file
After Width: | Height: | Size: 607 B |
BIN
dist/dwarf_right.png
vendored
Normal file
After Width: | Height: | Size: 629 B |
BIN
dist/grass01.png
vendored
Normal file
After Width: | Height: | Size: 614 B |
BIN
dist/rock.png
vendored
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
dist/soil01.png
vendored
Normal file
After Width: | Height: | Size: 586 B |
BIN
dist/soil_gravel01.png
vendored
Normal file
After Width: | Height: | Size: 940 B |
BIN
dist/tree_crown_left.png
vendored
Normal file
After Width: | Height: | Size: 719 B |
BIN
dist/tree_crown_left_mixed.png
vendored
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
dist/tree_crown_middle.png
vendored
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
dist/tree_crown_right.png
vendored
Normal file
After Width: | Height: | Size: 1 KiB |
BIN
dist/tree_crown_right_mixed.png
vendored
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
dist/tree_root_left.png
vendored
Normal file
After Width: | Height: | Size: 340 B |
BIN
dist/tree_root_left_mixed.png
vendored
Normal file
After Width: | Height: | Size: 539 B |
BIN
dist/tree_root_middle.png
vendored
Normal file
After Width: | Height: | Size: 938 B |
BIN
dist/tree_root_right.png
vendored
Normal file
After Width: | Height: | Size: 280 B |
BIN
dist/tree_root_right_mixed.png
vendored
Normal file
After Width: | Height: | Size: 539 B |
BIN
dist/tree_top_left.png
vendored
Normal file
After Width: | Height: | Size: 139 B |
BIN
dist/tree_top_left_mixed.png
vendored
Normal file
After Width: | Height: | Size: 257 B |
BIN
dist/tree_top_middle.png
vendored
Normal file
After Width: | Height: | Size: 747 B |
BIN
dist/tree_top_right.png
vendored
Normal file
After Width: | Height: | Size: 205 B |
BIN
dist/tree_top_right_mixed.png
vendored
Normal file
After Width: | Height: | Size: 257 B |
BIN
dist/tree_trunk_left.png
vendored
Normal file
After Width: | Height: | Size: 735 B |
BIN
dist/tree_trunk_left_mixed.png
vendored
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
dist/tree_trunk_middle.png
vendored
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
dist/tree_trunk_right.png
vendored
Normal file
After Width: | Height: | Size: 750 B |
BIN
dist/tree_trunk_right_mixed.png
vendored
Normal file
After Width: | Height: | Size: 1.1 KiB |
|
@ -5,10 +5,12 @@
|
||||||
@keydown.up="goUp($event)"
|
@keydown.up="goUp($event)"
|
||||||
@keydown.right="goRight($event)"
|
@keydown.right="goRight($event)"
|
||||||
@keydown.left="goLeft($event)"
|
@keydown.left="goLeft($event)"
|
||||||
|
@keydown.space="jump($event)"
|
||||||
/>
|
/>
|
||||||
<div id="level-indicator">x:{{ x }}, y:{{ y }}</div>
|
<div id="level-indicator">x:{{ x }}, y:{{ y }}</div>
|
||||||
|
<div id="player" :class="[player_direction]" />
|
||||||
<template v-for="row in rows">
|
<template v-for="row in rows">
|
||||||
<div v-for="block in row" class="block" :class="[block.type, block.background]" />
|
<div v-for="block in row" class="block" :class="[block.type]" />
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -18,6 +20,8 @@ import Level from './level'
|
||||||
|
|
||||||
const WIDTH = 32
|
const WIDTH = 32
|
||||||
const HEIGHT = 32
|
const HEIGHT = 32
|
||||||
|
const PLAYER_X = ~~(WIDTH / 2) - 1
|
||||||
|
const PLAYER_Y = HEIGHT - 16
|
||||||
const level = new Level(WIDTH, HEIGHT)
|
const level = new Level(WIDTH, HEIGHT)
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -27,34 +31,82 @@ export default {
|
||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
player_x: 0,
|
player_x: 0,
|
||||||
player_y: 0
|
player_y: 0,
|
||||||
|
player_direction: 'left'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
this.findStartPos()
|
this.findStartPos()
|
||||||
|
this.mindTheGap()
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
rows () {
|
rows () {
|
||||||
return level.grid(this.x, this.y, this.player_x, this.player_y)
|
return level.grid(this.x, this.y, this.player_x, this.player_y)
|
||||||
|
},
|
||||||
|
blockAtPlayer () {
|
||||||
|
return this.rows[PLAYER_Y][PLAYER_X]
|
||||||
|
},
|
||||||
|
blockLeftOfPlayer () {
|
||||||
|
return this.rows[PLAYER_Y][PLAYER_X - 1]
|
||||||
|
},
|
||||||
|
blockRightOfPlayer () {
|
||||||
|
return this.rows[PLAYER_Y][PLAYER_X + 1]
|
||||||
|
},
|
||||||
|
blockBelowPlayer () {
|
||||||
|
return this.rows[PLAYER_Y + 1][PLAYER_X]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
goDown (ev) {
|
goDown (ev) {
|
||||||
if (ev.shiftKey) this.y += 32
|
// TODO: this.player_direction = 'back'
|
||||||
else this.y++
|
if (this.blockBelowPlayer.walkable) this.y++
|
||||||
|
this.mindTheGap()
|
||||||
},
|
},
|
||||||
goUp (ev) {
|
goUp (ev) {
|
||||||
if (ev.shiftKey) this.y -= 32
|
// TODO: this.player_direction = 'back'
|
||||||
else this.y--
|
if (this.blockAtPlayer.climbable) this.y--
|
||||||
this.y = Math.max(0, this.y)
|
|
||||||
},
|
},
|
||||||
goRight (ev) {
|
goRight (ev) {
|
||||||
if (ev.shiftKey) this.x += 32
|
if (this.player_direction !== 'right') {
|
||||||
else this.x++
|
this.player_direction = 'right'
|
||||||
|
} else if (this.blockRightOfPlayer.walkable) {
|
||||||
|
this.x++
|
||||||
|
this.mindTheGap()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
goLeft (ev) {
|
goLeft (ev) {
|
||||||
if (ev.shiftKey) this.x -= 32
|
if (this.player_direction !== 'left') {
|
||||||
else this.x--
|
this.player_direction = 'left'
|
||||||
|
} else if (this.blockLeftOfPlayer.walkable) {
|
||||||
|
this.x--
|
||||||
|
this.mindTheGap()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
jump (ev) {
|
||||||
|
this.y--
|
||||||
|
if (this.player_direction === 'left' && this.blockLeftOfPlayer.walkable) {
|
||||||
|
this.x--
|
||||||
|
setTimeout(() => {
|
||||||
|
if (this.blockLeftOfPlayer.walkable) this.x--
|
||||||
|
if (this.blockBelowPlayer.walkable) this.y++
|
||||||
|
}, 50)
|
||||||
|
} else if (this.player_direction === 'right' && this.blockRightOfPlayer.walkable) {
|
||||||
|
this.x++
|
||||||
|
setTimeout(() => {
|
||||||
|
if (this.blockRightOfPlayer.walkable) this.x++
|
||||||
|
if (this.blockBelowPlayer.walkable) this.y++
|
||||||
|
}, 50)
|
||||||
|
}
|
||||||
|
// just jump while facing the back
|
||||||
|
setTimeout(() => this.mindTheGap(), 100)
|
||||||
|
},
|
||||||
|
mindTheGap () {
|
||||||
|
const below = this.blockBelowPlayer
|
||||||
|
console.log('mindTheGap', below)
|
||||||
|
if (below.walkable && !below.climbable) {
|
||||||
|
this.y++
|
||||||
|
setTimeout(() => this.mindTheGap(), 50)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
findStartPos () {
|
findStartPos () {
|
||||||
const x = parseInt(WIDTH / 2)
|
const x = parseInt(WIDTH / 2)
|
||||||
|
@ -67,7 +119,7 @@ export default {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -93,16 +145,23 @@ export default {
|
||||||
right: 0;
|
right: 0;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
.block {
|
#player {
|
||||||
|
position: absolute;
|
||||||
|
left: calc(32px * 15);
|
||||||
|
top: calc(32px * 16);
|
||||||
|
background-image: url(./assets/dwarf_right.png);
|
||||||
|
}
|
||||||
|
#player.left { background-image: url(./assets/dwarf_left.png); }
|
||||||
|
#player, .block {
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
width: 32px;
|
width: 32px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
background-color: #56F;
|
background-color: transparent;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
}
|
}
|
||||||
.block.air { background-color: #56F; }
|
.block { background-color: #56F; }
|
||||||
.block.grass { background-image: url(./assets/grass01.png); }
|
.block.grass { background-image: url(./assets/grass01.png); }
|
||||||
|
|
||||||
.block.tree_top_left { background-image: url(./assets/tree_top_left.png); }
|
.block.tree_top_left { background-image: url(./assets/tree_top_left.png); }
|
||||||
|
@ -137,6 +196,5 @@ export default {
|
||||||
.block.stone { background-image: url(./assets/rock.png); }
|
.block.stone { background-image: url(./assets/rock.png); }
|
||||||
.block.bedrock { background-image: url(./assets/bedrock.png); }
|
.block.bedrock { background-image: url(./assets/bedrock.png); }
|
||||||
.block.cave { background-color: #000; }
|
.block.cave { background-color: #000; }
|
||||||
.block.player { background-image: url(./assets/dwarf.png); }
|
.block:hover, .block.highlight { filter: brightness(1.4); }
|
||||||
.block:hover { filter: brightness(1.4); }
|
|
||||||
</style>
|
</style>
|
||||||
|
|
BIN
src/assets/demon_left.png
Normal file
After Width: | Height: | Size: 554 B |
BIN
src/assets/demon_right.png
Normal file
After Width: | Height: | Size: 564 B |
Before Width: | Height: | Size: 1.1 KiB |
BIN
src/assets/dwarf_left.png
Normal file
After Width: | Height: | Size: 607 B |
BIN
src/assets/dwarf_right.png
Normal file
After Width: | Height: | Size: 629 B |
BIN
src/assets/ghost_left.png
Normal file
After Width: | Height: | Size: 460 B |
BIN
src/assets/ghost_right.png
Normal file
After Width: | Height: | Size: 448 B |
BIN
src/assets/knight_left.png
Normal file
After Width: | Height: | Size: 595 B |
BIN
src/assets/knight_right.png
Normal file
After Width: | Height: | Size: 620 B |
BIN
src/assets/monsterboy_assets.png
Normal file
After Width: | Height: | Size: 156 KiB |
BIN
src/assets/shrooman_left.png
Normal file
After Width: | Height: | Size: 540 B |
BIN
src/assets/shrooman_right.png
Normal file
After Width: | Height: | Size: 537 B |
BIN
src/assets/shroomy_left.png
Normal file
After Width: | Height: | Size: 344 B |
BIN
src/assets/shroomy_right.png
Normal file
After Width: | Height: | Size: 329 B |
BIN
src/assets/skeleton_left.png
Normal file
After Width: | Height: | Size: 567 B |
BIN
src/assets/skeleton_right.png
Normal file
After Width: | Height: | Size: 551 B |
|
@ -7,15 +7,15 @@ export const type = {
|
||||||
tree_top_right: {type: 'tree_top_right', hp: 5, walkable: true},
|
tree_top_right: {type: 'tree_top_right', hp: 5, walkable: true},
|
||||||
|
|
||||||
tree_crown_left: {type: 'tree_crown_left', hp: 5, walkable: true},
|
tree_crown_left: {type: 'tree_crown_left', hp: 5, walkable: true},
|
||||||
tree_crown_middle: {type: 'tree_crown_middle', hp: 5, walkable: true},
|
tree_crown_middle: {type: 'tree_crown_middle', hp: 5, walkable: true, climbable: true},
|
||||||
tree_crown_right: {type: 'tree_crown_right', hp: 5, walkable: true},
|
tree_crown_right: {type: 'tree_crown_right', hp: 5, walkable: true},
|
||||||
|
|
||||||
tree_trunk_left: {type: 'tree_trunk_left', hp: 5, walkable: true},
|
tree_trunk_left: {type: 'tree_trunk_left', hp: 5, walkable: true},
|
||||||
tree_trunk_middle: {type: 'tree_trunk_middle', hp: 5, walkable: true},
|
tree_trunk_middle: {type: 'tree_trunk_middle', hp: 5, walkable: true, climbable: true},
|
||||||
tree_trunk_right: {type: 'tree_trunk_right', hp: 5, walkable: true},
|
tree_trunk_right: {type: 'tree_trunk_right', hp: 5, walkable: true},
|
||||||
|
|
||||||
tree_root_left: {type: 'tree_root_left', hp: 5, walkable: true},
|
tree_root_left: {type: 'tree_root_left', hp: 5, walkable: true},
|
||||||
tree_root_middle: {type: 'tree_root_middle', hp: 5, walkable: true},
|
tree_root_middle: {type: 'tree_root_middle', hp: 5, walkable: true, climbable: true},
|
||||||
tree_root_right: {type: 'tree_root_right', hp: 5, walkable: true},
|
tree_root_right: {type: 'tree_root_right', hp: 5, walkable: true},
|
||||||
|
|
||||||
tree_top_left_mixed: {type: 'tree_top_left_mixed', hp: 5, walkable: true},
|
tree_top_left_mixed: {type: 'tree_top_left_mixed', hp: 5, walkable: true},
|
||||||
|
|
|
@ -18,12 +18,12 @@ export default class Level {
|
||||||
this.player = new Player(this._grid)
|
this.player = new Player(this._grid)
|
||||||
}
|
}
|
||||||
|
|
||||||
grid (x, y, px, py) {
|
grid (x, y) {
|
||||||
this.generate(x, y, this._w, this._h, px, py)
|
this.generate(x, y, this._w, this._h)
|
||||||
return this._grid
|
return this._grid
|
||||||
}
|
}
|
||||||
|
|
||||||
generate (x, y, w, h, px, py) {
|
generate (x, y, w, h) {
|
||||||
for (let i = 0; i < h; i++) {
|
for (let i = 0; i < h; i++) {
|
||||||
const level = y + i
|
const level = y + i
|
||||||
const column = x
|
const column = x
|
||||||
|
@ -33,6 +33,5 @@ export default class Level {
|
||||||
this.blockExt.level(level, column, row, previousRow)
|
this.blockExt.level(level, column, row, previousRow)
|
||||||
this._grid[i] = row
|
this._grid[i] = row
|
||||||
}
|
}
|
||||||
this.player.setPosition(px, py)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,13 +5,4 @@ export default class Player {
|
||||||
this._player_changes = []
|
this._player_changes = []
|
||||||
this._grid = grid
|
this._grid = grid
|
||||||
}
|
}
|
||||||
|
|
||||||
setPosition (px, py) {
|
|
||||||
const block = this._grid[py][px]
|
|
||||||
|
|
||||||
if (block.walkable) {
|
|
||||||
T.player.background = block.type
|
|
||||||
this._grid[py][px] = T.player
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|