clean up field component, make jumps more "realistic"
This commit is contained in:
parent
062d249d00
commit
54f352c577
3 changed files with 142 additions and 98 deletions
47
package-lock.json
generated
47
package-lock.json
generated
|
@ -2783,6 +2783,7 @@
|
|||
"version": "0.0.9",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"inherits": "~2.0.0"
|
||||
}
|
||||
|
@ -2807,7 +2808,8 @@
|
|||
"buffer-shims": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"caseless": {
|
||||
"version": "0.12.0",
|
||||
|
@ -2824,12 +2826,14 @@
|
|||
"code-point-at": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"combined-stream": {
|
||||
"version": "1.0.5",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
}
|
||||
|
@ -2842,17 +2846,20 @@
|
|||
"console-control-strings": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"cryptiles": {
|
||||
"version": "2.0.5",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"boom": "2.x.x"
|
||||
}
|
||||
|
@ -2892,7 +2899,8 @@
|
|||
"delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"delegates": {
|
||||
"version": "1.0.0",
|
||||
|
@ -2924,7 +2932,8 @@
|
|||
"extsprintf": {
|
||||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"forever-agent": {
|
||||
"version": "0.6.1",
|
||||
|
@ -3047,6 +3056,7 @@
|
|||
"version": "3.1.3",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"boom": "2.x.x",
|
||||
"cryptiles": "2.x.x",
|
||||
|
@ -3094,6 +3104,7 @@
|
|||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"number-is-nan": "1.0.1"
|
||||
}
|
||||
|
@ -3107,7 +3118,8 @@
|
|||
"isarray": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"isstream": {
|
||||
"version": "0.1.2",
|
||||
|
@ -3180,12 +3192,14 @@
|
|||
"mime-db": {
|
||||
"version": "1.27.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.15",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"mime-db": "1.27.0"
|
||||
}
|
||||
|
@ -3261,7 +3275,8 @@
|
|||
"number-is-nan": {
|
||||
"version": "1.0.1",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"oauth-sign": {
|
||||
"version": "0.8.2",
|
||||
|
@ -3319,7 +3334,8 @@
|
|||
"process-nextick-args": {
|
||||
"version": "1.0.7",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"punycode": {
|
||||
"version": "1.4.1",
|
||||
|
@ -3357,6 +3373,7 @@
|
|||
"version": "2.2.9",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"buffer-shims": "~1.0.0",
|
||||
"core-util-is": "~1.0.0",
|
||||
|
@ -3408,7 +3425,8 @@
|
|||
"safe-buffer": {
|
||||
"version": "5.0.1",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"semver": {
|
||||
"version": "5.3.0",
|
||||
|
@ -3432,6 +3450,7 @@
|
|||
"version": "1.0.9",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"hoek": "2.x.x"
|
||||
}
|
||||
|
@ -3465,6 +3484,7 @@
|
|||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"code-point-at": "^1.0.0",
|
||||
"is-fullwidth-code-point": "^1.0.0",
|
||||
|
@ -3475,6 +3495,7 @@
|
|||
"version": "1.0.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
|
@ -3503,6 +3524,7 @@
|
|||
"version": "2.2.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"block-stream": "*",
|
||||
"fstream": "^1.0.2",
|
||||
|
@ -3558,7 +3580,8 @@
|
|||
"util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"uuid": {
|
||||
"version": "3.0.1",
|
||||
|
|
133
src/Field.vue
133
src/Field.vue
|
@ -1,14 +1,12 @@
|
|||
<template>
|
||||
<div id="field" :class="daytimeClass">
|
||||
<input v-keep-focussed type="text"
|
||||
@keydown.up="player_velocity_y = -8"
|
||||
@keydown.down="player_velocity_y = 8"
|
||||
@keydown.up="jump = jump ? jump : 16"
|
||||
@keydown.right="player_velocity_x = 8"
|
||||
@keydown.left="player_velocity_x = -8"
|
||||
@keyup.up="player_velocity_y = 8"
|
||||
@keyup.down="player_velocity_y = 8"
|
||||
@keyup.right="player_velocity_x = 0"
|
||||
@keyup.left="player_velocity_x = 0"
|
||||
@keypress.p="togglePause"
|
||||
/>
|
||||
<mountain-background :x="128 + x / 8" :time="time" />
|
||||
<div id="wrap" :style="{transform: `translate(${tx}px, ${ty}px)`}">
|
||||
|
@ -17,13 +15,18 @@
|
|||
</template>
|
||||
</div>
|
||||
<div id="player" :class="[player_direction]" />
|
||||
<div id="level-indicator">x:{{ floorX }}, y:{{ floorY }} ({{clock}})</div>
|
||||
<div id="level-indicator">
|
||||
x:{{ floorX }}, y:{{ floorY }}
|
||||
<template v-if="moving !== false">({{clock}})</template>
|
||||
<template v-else>(PAUSED)</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// import throttle from 'lodash/throttle'
|
||||
import Level from './level'
|
||||
import Player from './player'
|
||||
import MountainBackground from './Background'
|
||||
|
||||
const BLOCK_SIZE = 32
|
||||
|
@ -42,7 +45,8 @@ export default {
|
|||
y: 0,
|
||||
player_direction: 'left',
|
||||
player_velocity_x: 0,
|
||||
player_velocity_y: 9,
|
||||
player_velocity_y: 8,
|
||||
jump: 0,
|
||||
gravity: 8.0 / 20,
|
||||
moving: false,
|
||||
time: 250
|
||||
|
@ -62,22 +66,30 @@ export default {
|
|||
}
|
||||
},
|
||||
computed: {
|
||||
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] },
|
||||
blockAbovePlayer () { return this.rows[PLAYER_Y - 1][PLAYER_X] },
|
||||
blockBelowPlayer () { return this.rows[PLAYER_Y + 1][PLAYER_X] },
|
||||
blockedUp () { return !this.blockAbovePlayer.walkable },
|
||||
blockedDown () { return !this.blockBelowPlayer.walkable },
|
||||
blockedLeft () { return !this.blockLeftOfPlayer.walkable },
|
||||
blockedRight () { return !this.blockRightOfPlayer.walkable },
|
||||
rows () { return level.grid(this.floorX, this.floorY) },
|
||||
surroundings () {
|
||||
const at = this.rows[PLAYER_Y][PLAYER_X]
|
||||
const left = this.rows[PLAYER_Y][PLAYER_X - 1]
|
||||
const right = this.rows[PLAYER_Y][PLAYER_X + 1]
|
||||
const above = this.rows[PLAYER_Y - 1][PLAYER_X]
|
||||
const below = this.rows[PLAYER_Y + 1][PLAYER_X]
|
||||
|
||||
const blocked = {
|
||||
at: !at.walkable,
|
||||
left: !left.walkable,
|
||||
right: !right.walkable,
|
||||
above: !above.walkable,
|
||||
below: !below.walkable
|
||||
}
|
||||
|
||||
return { at, left, right, below, blocked }
|
||||
},
|
||||
cornerX () { return this.x === ~~this.x }, // cornering a block
|
||||
cornerY () { return this.y === ~~this.y },
|
||||
floorX () { return Math.floor(this.x) },
|
||||
floorY () { return Math.floor(this.y) },
|
||||
tx () { return (this.x - this.floorX) * -BLOCK_SIZE },
|
||||
ty () { return (this.y - this.floorY) * -BLOCK_SIZE },
|
||||
rows () { return level.grid(this.floorX, this.floorY) },
|
||||
daytimeClass () {
|
||||
const t = this.time
|
||||
if (t >= 900 || t < 80) return "night"
|
||||
|
@ -109,46 +121,40 @@ export default {
|
|||
|
||||
// this.player_velocity_y += this.gravity
|
||||
let vx = this.player_velocity_x * RECIPROCAL
|
||||
let vy = this.player_velocity_y * RECIPROCAL
|
||||
let vy = (this.player_velocity_y - this.jump) * RECIPROCAL
|
||||
|
||||
if (this.jump > 0) this.jump--
|
||||
|
||||
// change player graphic according to direction
|
||||
if (vx < 0) this.player_direction = 'left'
|
||||
if (vx > 0) this.player_direction = 'right'
|
||||
|
||||
// don't walk / fall into blocks
|
||||
if (vx > 0 && this.blockedRight) vx = 0
|
||||
if (vx < 0 && this.blockedLeft) vx = 0
|
||||
if (vy > 0 && this.blockedDown) {
|
||||
// jump to the top of the block
|
||||
vy = -((~~y + 1) - y) + 1
|
||||
// vy = 0
|
||||
}
|
||||
if (vy < 0 && this.blockedUp) vy = 0
|
||||
const { blocked } = this.surroundings
|
||||
if (vx > 0 && blocked.right) vx = 0
|
||||
if (vx < 0 && blocked.left) vx = 0
|
||||
if (vy > 0 && blocked.below) vy = 0
|
||||
if (vy < 0 && blocked.above) vy = 0
|
||||
|
||||
this.x += vx
|
||||
this.y += vy
|
||||
this.moving = setTimeout(() => this.move(), 50)
|
||||
this.moving = setTimeout(() => this.move(), 64) // roughly every 4 frames
|
||||
},
|
||||
togglePause () {
|
||||
if (this.moving === false) { // is paused
|
||||
this.moving = true // avoid (unlikely) race condition
|
||||
this.move()
|
||||
} else {
|
||||
clearTimeout(this.moving)
|
||||
this.moving = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style src="./assets/field.css" />
|
||||
<style>
|
||||
#field {
|
||||
position: relative;
|
||||
width: 1024px;
|
||||
height: 1024px;
|
||||
margin: auto;
|
||||
overflow: hidden;
|
||||
background-color: #56F;
|
||||
}
|
||||
#field > input {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
display: block;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
}
|
||||
#level-indicator {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
|
@ -183,49 +189,4 @@ export default {
|
|||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
}
|
||||
.block.grass { background-image: url(./assets/grass01.png); }
|
||||
|
||||
.block.tree_top_left { background-image: url(./assets/tree_top_left.png); }
|
||||
.block.tree_top_middle { background-image: url(./assets/tree_top_middle.png); }
|
||||
.block.tree_top_right { background-image: url(./assets/tree_top_right.png); }
|
||||
|
||||
.block.tree_crown_left { background-image: url(./assets/tree_crown_left.png); }
|
||||
.block.tree_crown_middle { background-image: url(./assets/tree_crown_middle.png); }
|
||||
.block.tree_crown_right { background-image: url(./assets/tree_crown_right.png); }
|
||||
|
||||
.block.tree_trunk_left { background-image: url(./assets/tree_trunk_left.png); }
|
||||
.block.tree_trunk_middle { background-image: url(./assets/tree_trunk_middle.png); }
|
||||
.block.tree_trunk_right { background-image: url(./assets/tree_trunk_right.png); }
|
||||
|
||||
.block.tree_root_left { background-image: url(./assets/tree_root_left.png); }
|
||||
.block.tree_root_middle { background-image: url(./assets/tree_root_middle.png); }
|
||||
.block.tree_root_right { background-image: url(./assets/tree_root_right.png); }
|
||||
|
||||
.block.tree_top_left_mixed { background-image: url(./assets/tree_top_left_mixed.png); }
|
||||
.block.tree_crown_left_mixed { background-image: url(./assets/tree_crown_left_mixed.png); }
|
||||
.block.tree_trunk_left_mixed { background-image: url(./assets/tree_trunk_left_mixed.png); }
|
||||
.block.tree_root_left_mixed { background-image: url(./assets/tree_root_left_mixed.png); }
|
||||
|
||||
.block.tree_top_right_mixed { background-image: url(./assets/tree_top_right_mixed.png); }
|
||||
.block.tree_crown_right_mixed { background-image: url(./assets/tree_crown_right_mixed.png); }
|
||||
.block.tree_trunk_right_mixed { background-image: url(./assets/tree_trunk_right_mixed.png); }
|
||||
.block.tree_root_right_mixed { background-image: url(./assets/tree_root_right_mixed.png); }
|
||||
|
||||
.block.soil { background-image: url(./assets/soil.png); }
|
||||
.block.soil_gravel { background-image: url(./assets/soil_gravel.png); }
|
||||
.block.stone_gravel { background-image: url(./assets/rock_gravel.png); }
|
||||
.block.stone { background-image: url(./assets/rock.png); }
|
||||
.block.bedrock { background-image: url(./assets/bedrock.png); }
|
||||
.block.cave { background-color: #000; }
|
||||
#field .block:hover { outline: 1px solid white; z-index: 10; }
|
||||
|
||||
.morning0 .block, .morning0 #player { filter: saturate(50%) brightness(0.6) hue-rotate(-10deg); }
|
||||
.morning1 .block, .morning1 #player { filter: saturate(100%) brightness(0.8) hue-rotate(-20deg); }
|
||||
.morning2 .block, .morning2 #player { filter: saturate(200%) hue-rotate(-30deg); }
|
||||
|
||||
.evening0 .block, .evening0 #player { filter: brightness(0.8) hue-rotate(-10deg); }
|
||||
.evening1 .block, .evening1 #player { filter: brightness(0.6) hue-rotate(-20deg); }
|
||||
.evening2 .block, .evening2 #player { filter: brightness(0.4) hue-rotate(-10deg) saturate(50%); }
|
||||
|
||||
.night .block, .night #player { filter: brightness(0.3) saturate(30%); }
|
||||
</style>
|
||||
|
|
60
src/assets/field.css
Normal file
60
src/assets/field.css
Normal file
|
@ -0,0 +1,60 @@
|
|||
#field {
|
||||
position: relative;
|
||||
width: 1024px;
|
||||
height: 1024px;
|
||||
margin: auto;
|
||||
overflow: hidden;
|
||||
background-color: #56F;
|
||||
}
|
||||
#field > input {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
display: block;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
}
|
||||
.block.grass { background-image: url(./grass01.png); }
|
||||
|
||||
.block.tree_top_left { background-image: url(./tree_top_left.png); }
|
||||
.block.tree_top_middle { background-image: url(./tree_top_middle.png); }
|
||||
.block.tree_top_right { background-image: url(./tree_top_right.png); }
|
||||
|
||||
.block.tree_crown_left { background-image: url(./tree_crown_left.png); }
|
||||
.block.tree_crown_middle { background-image: url(./tree_crown_middle.png); }
|
||||
.block.tree_crown_right { background-image: url(./tree_crown_right.png); }
|
||||
|
||||
.block.tree_trunk_left { background-image: url(./tree_trunk_left.png); }
|
||||
.block.tree_trunk_middle { background-image: url(./tree_trunk_middle.png); }
|
||||
.block.tree_trunk_right { background-image: url(./tree_trunk_right.png); }
|
||||
|
||||
.block.tree_root_left { background-image: url(./tree_root_left.png); }
|
||||
.block.tree_root_middle { background-image: url(./tree_root_middle.png); }
|
||||
.block.tree_root_right { background-image: url(./tree_root_right.png); }
|
||||
|
||||
.block.tree_top_left_mixed { background-image: url(./tree_top_left_mixed.png); }
|
||||
.block.tree_crown_left_mixed { background-image: url(./tree_crown_left_mixed.png); }
|
||||
.block.tree_trunk_left_mixed { background-image: url(./tree_trunk_left_mixed.png); }
|
||||
.block.tree_root_left_mixed { background-image: url(./tree_root_left_mixed.png); }
|
||||
|
||||
.block.tree_top_right_mixed { background-image: url(./tree_top_right_mixed.png); }
|
||||
.block.tree_crown_right_mixed { background-image: url(./tree_crown_right_mixed.png); }
|
||||
.block.tree_trunk_right_mixed { background-image: url(./tree_trunk_right_mixed.png); }
|
||||
.block.tree_root_right_mixed { background-image: url(./tree_root_right_mixed.png); }
|
||||
|
||||
.block.soil { background-image: url(./soil.png); }
|
||||
.block.soil_gravel { background-image: url(./soil_gravel.png); }
|
||||
.block.stone_gravel { background-image: url(./rock_gravel.png); }
|
||||
.block.stone { background-image: url(./rock.png); }
|
||||
.block.bedrock { background-image: url(./bedrock.png); }
|
||||
.block.cave { background-color: #000; }
|
||||
#field .block:hover { outline: 1px solid white; z-index: 10; }
|
||||
|
||||
.morning0 .block, .morning0 #player { filter: saturate(50%) brightness(0.6) hue-rotate(-10deg); }
|
||||
.morning1 .block, .morning1 #player { filter: saturate(100%) brightness(0.8) hue-rotate(-20deg); }
|
||||
.morning2 .block, .morning2 #player { filter: saturate(200%) hue-rotate(-30deg); }
|
||||
|
||||
.evening0 .block, .evening0 #player { filter: brightness(0.8) hue-rotate(-10deg); }
|
||||
.evening1 .block, .evening1 #player { filter: brightness(0.6) hue-rotate(-20deg); }
|
||||
.evening2 .block, .evening2 #player { filter: brightness(0.4) hue-rotate(-10deg) saturate(50%); }
|
||||
|
||||
.night .block, .night #player { filter: brightness(0.3) saturate(30%); }
|
Loading…
Reference in a new issue